1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/fxfa/fm2js/cxfa_fmparser.h"
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "core/fxcrt/autorestorer.h"
14 #include "third_party/base/ptr_util.h"
15
16 namespace {
17
18 const unsigned int kMaxAssignmentChainLength = 12;
19 const unsigned int kMaxParseDepth = 1250;
20
21 } // namespace
22
CXFA_FMParser(const WideStringView & wsFormcalc)23 CXFA_FMParser::CXFA_FMParser(const WideStringView& wsFormcalc)
24 : m_error(false), m_parse_depth(0), m_max_parse_depth(kMaxParseDepth) {
25 m_lexer = pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc);
26 m_token = m_lexer->NextToken();
27 }
28
~CXFA_FMParser()29 CXFA_FMParser::~CXFA_FMParser() {}
30
Parse()31 std::unique_ptr<CXFA_FMFunctionDefinition> CXFA_FMParser::Parse() {
32 auto expressions = ParseTopExpression();
33 if (HasError())
34 return nullptr;
35
36 std::vector<WideStringView> arguments;
37 return pdfium::MakeUnique<CXFA_FMFunctionDefinition>(
38 1, true, L"", std::move(arguments), std::move(expressions));
39 }
40
NextToken()41 bool CXFA_FMParser::NextToken() {
42 if (HasError())
43 return false;
44 m_token = m_lexer->NextToken();
45 while (!HasError() && m_token->m_type == TOKreserver)
46 m_token = m_lexer->NextToken();
47 return !HasError();
48 }
49
CheckThenNext(XFA_FM_TOKEN op)50 bool CXFA_FMParser::CheckThenNext(XFA_FM_TOKEN op) {
51 if (HasError())
52 return false;
53
54 if (m_token->m_type != op) {
55 m_error = true;
56 return false;
57 }
58 return NextToken();
59 }
60
IncrementParseDepthAndCheck()61 bool CXFA_FMParser::IncrementParseDepthAndCheck() {
62 return ++m_parse_depth < m_max_parse_depth;
63 }
64
65 std::vector<std::unique_ptr<CXFA_FMExpression>>
ParseTopExpression()66 CXFA_FMParser::ParseTopExpression() {
67 AutoRestorer<unsigned long> restorer(&m_parse_depth);
68 if (HasError() || !IncrementParseDepthAndCheck())
69 return std::vector<std::unique_ptr<CXFA_FMExpression>>();
70
71 std::unique_ptr<CXFA_FMExpression> expr;
72 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
73 while (!HasError()) {
74 if (m_token->m_type == TOKeof || m_token->m_type == TOKendfunc ||
75 m_token->m_type == TOKendif || m_token->m_type == TOKelseif ||
76 m_token->m_type == TOKelse || m_token->m_type == TOKreserver) {
77 return expressions;
78 }
79
80 expr = m_token->m_type == TOKfunc ? ParseFunction() : ParseExpression();
81 if (!expr) {
82 m_error = true;
83 break;
84 }
85 expressions.push_back(std::move(expr));
86 }
87 return std::vector<std::unique_ptr<CXFA_FMExpression>>();
88 }
89
ParseFunction()90 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseFunction() {
91 AutoRestorer<unsigned long> restorer(&m_parse_depth);
92 if (HasError() || !IncrementParseDepthAndCheck())
93 return nullptr;
94
95 WideStringView ident;
96 std::vector<WideStringView> arguments;
97 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
98 uint32_t line = m_token->m_line_num;
99 if (!NextToken())
100 return nullptr;
101 if (m_token->m_type != TOKidentifier) {
102 m_error = true;
103 return nullptr;
104 } else {
105 ident = m_token->m_string;
106 if (!NextToken())
107 return nullptr;
108 }
109 if (!CheckThenNext(TOKlparen))
110 return nullptr;
111 if (m_token->m_type == TOKrparen) {
112 if (!NextToken())
113 return nullptr;
114 } else {
115 while (1) {
116 if (m_token->m_type != TOKidentifier) {
117 m_error = true;
118 return nullptr;
119 }
120 arguments.push_back(m_token->m_string);
121 if (!NextToken())
122 return nullptr;
123 if (m_token->m_type == TOKcomma) {
124 if (!NextToken())
125 return nullptr;
126 continue;
127 }
128 if (m_token->m_type == TOKrparen) {
129 if (!NextToken())
130 return nullptr;
131 } else {
132 if (!CheckThenNext(TOKrparen))
133 return nullptr;
134 }
135 break;
136 }
137 }
138 if (!CheckThenNext(TOKdo))
139 return nullptr;
140 if (m_token->m_type == TOKendfunc) {
141 if (!NextToken())
142 return nullptr;
143 } else {
144 expressions = ParseTopExpression();
145 if (!expressions.size() || !CheckThenNext(TOKendfunc))
146 return nullptr;
147 }
148
149 return pdfium::MakeUnique<CXFA_FMFunctionDefinition>(
150 line, false, ident, std::move(arguments), std::move(expressions));
151 }
152
ParseExpression()153 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpression() {
154 AutoRestorer<unsigned long> restorer(&m_parse_depth);
155 if (HasError() || !IncrementParseDepthAndCheck())
156 return nullptr;
157
158 std::unique_ptr<CXFA_FMExpression> expr;
159 uint32_t line = m_token->m_line_num;
160 switch (m_token->m_type) {
161 case TOKvar:
162 expr = ParseVarExpression();
163 break;
164 case TOKnull:
165 case TOKnumber:
166 case TOKstring:
167 case TOKplus:
168 case TOKminus:
169 case TOKksnot:
170 case TOKidentifier:
171 case TOKlparen:
172 expr = ParseExpExpression();
173 break;
174 case TOKif:
175 expr = ParseIfExpression();
176 break;
177 case TOKwhile:
178 expr = ParseWhileExpression();
179 break;
180 case TOKfor:
181 expr = ParseForExpression();
182 break;
183 case TOKforeach:
184 expr = ParseForeachExpression();
185 break;
186 case TOKdo:
187 expr = ParseDoExpression();
188 break;
189 case TOKbreak:
190 expr = pdfium::MakeUnique<CXFA_FMBreakExpression>(line);
191 if (!NextToken())
192 return nullptr;
193 break;
194 case TOKcontinue:
195 expr = pdfium::MakeUnique<CXFA_FMContinueExpression>(line);
196 if (!NextToken())
197 return nullptr;
198 break;
199 default:
200 m_error = true;
201 return nullptr;
202 }
203 return expr;
204 }
205
ParseVarExpression()206 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseVarExpression() {
207 AutoRestorer<unsigned long> restorer(&m_parse_depth);
208 if (HasError() || !IncrementParseDepthAndCheck())
209 return nullptr;
210
211 WideStringView ident;
212 uint32_t line = m_token->m_line_num;
213 if (!NextToken())
214 return nullptr;
215 if (m_token->m_type != TOKidentifier) {
216 m_error = true;
217 return nullptr;
218 }
219
220 ident = m_token->m_string;
221 if (!NextToken())
222 return nullptr;
223
224 std::unique_ptr<CXFA_FMExpression> expr;
225 if (m_token->m_type == TOKassign) {
226 if (!NextToken())
227 return nullptr;
228
229 expr = ParseExpExpression();
230 if (!expr)
231 return nullptr;
232 }
233
234 return pdfium::MakeUnique<CXFA_FMVarExpression>(line, ident, std::move(expr));
235 }
236
237 std::unique_ptr<CXFA_FMSimpleExpression>
ParseSimpleExpression()238 CXFA_FMParser::ParseSimpleExpression() {
239 if (HasError())
240 return nullptr;
241
242 uint32_t line = m_token->m_line_num;
243 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression();
244 if (!pExp1)
245 return nullptr;
246 int level = 1;
247 while (m_token->m_type == TOKassign) {
248 if (!NextToken())
249 return nullptr;
250 std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression();
251 if (!pExp2)
252 return nullptr;
253 if (level++ == kMaxAssignmentChainLength) {
254 m_error = true;
255 return nullptr;
256 }
257 pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>(
258 line, TOKassign, std::move(pExp1), std::move(pExp2));
259 }
260 return pExp1;
261 }
262
ParseExpExpression()263 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpExpression() {
264 AutoRestorer<unsigned long> restorer(&m_parse_depth);
265 if (HasError() || !IncrementParseDepthAndCheck())
266 return nullptr;
267
268 uint32_t line = m_token->m_line_num;
269 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression();
270 if (!pExp1)
271 return nullptr;
272 return pdfium::MakeUnique<CXFA_FMExpExpression>(line, std::move(pExp1));
273 }
274
275 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalOrExpression()276 CXFA_FMParser::ParseLogicalOrExpression() {
277 AutoRestorer<unsigned long> restorer(&m_parse_depth);
278 if (HasError() || !IncrementParseDepthAndCheck())
279 return nullptr;
280
281 uint32_t line = m_token->m_line_num;
282 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseLogicalAndExpression();
283 if (!e1)
284 return nullptr;
285
286 for (;;) {
287 switch (m_token->m_type) {
288 case TOKor:
289 case TOKksor: {
290 if (!NextToken())
291 return nullptr;
292
293 std::unique_ptr<CXFA_FMSimpleExpression> e2(
294 ParseLogicalAndExpression());
295 if (!e2)
296 return nullptr;
297
298 e1 = pdfium::MakeUnique<CXFA_FMLogicalOrExpression>(
299 line, TOKor, std::move(e1), std::move(e2));
300 continue;
301 }
302 default:
303 break;
304 }
305 break;
306 }
307 return e1;
308 }
309
310 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalAndExpression()311 CXFA_FMParser::ParseLogicalAndExpression() {
312 AutoRestorer<unsigned long> restorer(&m_parse_depth);
313 if (HasError() || !IncrementParseDepthAndCheck())
314 return nullptr;
315
316 uint32_t line = m_token->m_line_num;
317 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseEqualityExpression();
318 if (!e1)
319 return nullptr;
320
321 for (;;) {
322 switch (m_token->m_type) {
323 case TOKand:
324 case TOKksand: {
325 if (!NextToken())
326 return nullptr;
327
328 std::unique_ptr<CXFA_FMSimpleExpression> e2 = ParseEqualityExpression();
329 if (!e2)
330 return nullptr;
331
332 e1 = pdfium::MakeUnique<CXFA_FMLogicalAndExpression>(
333 line, TOKand, std::move(e1), std::move(e2));
334 continue;
335 }
336 default:
337 break;
338 }
339 break;
340 }
341 return e1;
342 }
343
344 std::unique_ptr<CXFA_FMSimpleExpression>
ParseEqualityExpression()345 CXFA_FMParser::ParseEqualityExpression() {
346 AutoRestorer<unsigned long> restorer(&m_parse_depth);
347 if (HasError() || !IncrementParseDepthAndCheck())
348 return nullptr;
349
350 uint32_t line = m_token->m_line_num;
351 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseRelationalExpression();
352 if (!e1)
353 return nullptr;
354 for (;;) {
355 std::unique_ptr<CXFA_FMSimpleExpression> e2;
356 switch (m_token->m_type) {
357 case TOKeq:
358 case TOKkseq:
359 if (!NextToken())
360 return nullptr;
361
362 e2 = ParseRelationalExpression();
363 if (!e2)
364 return nullptr;
365
366 e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>(
367 line, TOKeq, std::move(e1), std::move(e2));
368 continue;
369 case TOKne:
370 case TOKksne:
371 if (!NextToken())
372 return nullptr;
373
374 e2 = ParseRelationalExpression();
375 if (!e2)
376 return nullptr;
377
378 e1 = pdfium::MakeUnique<CXFA_FMEqualityExpression>(
379 line, TOKne, std::move(e1), std::move(e2));
380 continue;
381 default:
382 break;
383 }
384 break;
385 }
386 return e1;
387 }
388
389 std::unique_ptr<CXFA_FMSimpleExpression>
ParseRelationalExpression()390 CXFA_FMParser::ParseRelationalExpression() {
391 AutoRestorer<unsigned long> restorer(&m_parse_depth);
392 if (HasError() || !IncrementParseDepthAndCheck())
393 return nullptr;
394
395 uint32_t line = m_token->m_line_num;
396 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseAddtiveExpression();
397 if (!e1)
398 return nullptr;
399
400 for (;;) {
401 std::unique_ptr<CXFA_FMSimpleExpression> e2;
402 switch (m_token->m_type) {
403 case TOKlt:
404 case TOKkslt:
405 if (!NextToken())
406 return nullptr;
407
408 e2 = ParseAddtiveExpression();
409 if (!e2)
410 return nullptr;
411
412 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
413 line, TOKlt, std::move(e1), std::move(e2));
414 continue;
415 case TOKgt:
416 case TOKksgt:
417 if (!NextToken())
418 return nullptr;
419
420 e2 = ParseAddtiveExpression();
421 if (!e2)
422 return nullptr;
423
424 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
425 line, TOKgt, std::move(e1), std::move(e2));
426 continue;
427 case TOKle:
428 case TOKksle:
429 if (!NextToken())
430 return nullptr;
431
432 e2 = ParseAddtiveExpression();
433 if (!e2)
434 return nullptr;
435
436 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
437 line, TOKle, std::move(e1), std::move(e2));
438 continue;
439 case TOKge:
440 case TOKksge:
441 if (!NextToken())
442 return nullptr;
443
444 e2 = ParseAddtiveExpression();
445 if (!e2)
446 return nullptr;
447
448 e1 = pdfium::MakeUnique<CXFA_FMRelationalExpression>(
449 line, TOKge, std::move(e1), std::move(e2));
450 continue;
451 default:
452 break;
453 }
454 break;
455 }
456 return e1;
457 }
458
459 std::unique_ptr<CXFA_FMSimpleExpression>
ParseAddtiveExpression()460 CXFA_FMParser::ParseAddtiveExpression() {
461 AutoRestorer<unsigned long> restorer(&m_parse_depth);
462 if (HasError() || !IncrementParseDepthAndCheck())
463 return nullptr;
464
465 uint32_t line = m_token->m_line_num;
466 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseMultiplicativeExpression();
467 if (!e1)
468 return nullptr;
469
470 for (;;) {
471 std::unique_ptr<CXFA_FMSimpleExpression> e2;
472 switch (m_token->m_type) {
473 case TOKplus:
474 if (!NextToken())
475 return nullptr;
476
477 e2 = ParseMultiplicativeExpression();
478 if (!e2)
479 return nullptr;
480
481 e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>(
482 line, TOKplus, std::move(e1), std::move(e2));
483 continue;
484 case TOKminus:
485 if (!NextToken())
486 return nullptr;
487
488 e2 = ParseMultiplicativeExpression();
489 if (!e2)
490 return nullptr;
491
492 e1 = pdfium::MakeUnique<CXFA_FMAdditiveExpression>(
493 line, TOKminus, std::move(e1), std::move(e2));
494 continue;
495 default:
496 break;
497 }
498 break;
499 }
500 return e1;
501 }
502
503 std::unique_ptr<CXFA_FMSimpleExpression>
ParseMultiplicativeExpression()504 CXFA_FMParser::ParseMultiplicativeExpression() {
505 AutoRestorer<unsigned long> restorer(&m_parse_depth);
506 if (HasError() || !IncrementParseDepthAndCheck())
507 return nullptr;
508
509 uint32_t line = m_token->m_line_num;
510 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseUnaryExpression();
511 if (!e1)
512 return nullptr;
513
514 for (;;) {
515 std::unique_ptr<CXFA_FMSimpleExpression> e2;
516 switch (m_token->m_type) {
517 case TOKmul:
518 if (!NextToken())
519 return nullptr;
520
521 e2 = ParseUnaryExpression();
522 if (!e2)
523 return nullptr;
524
525 e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>(
526 line, TOKmul, std::move(e1), std::move(e2));
527 continue;
528 case TOKdiv:
529 if (!NextToken())
530 return nullptr;
531
532 e2 = ParseUnaryExpression();
533 if (!e2)
534 return nullptr;
535
536 e1 = pdfium::MakeUnique<CXFA_FMMultiplicativeExpression>(
537 line, TOKdiv, std::move(e1), std::move(e2));
538 continue;
539 default:
540 break;
541 }
542 break;
543 }
544 return e1;
545 }
546
ParseUnaryExpression()547 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseUnaryExpression() {
548 AutoRestorer<unsigned long> restorer(&m_parse_depth);
549 if (HasError() || !IncrementParseDepthAndCheck())
550 return nullptr;
551
552 std::unique_ptr<CXFA_FMSimpleExpression> expr;
553 uint32_t line = m_token->m_line_num;
554 switch (m_token->m_type) {
555 case TOKplus:
556 if (!NextToken())
557 return nullptr;
558
559 expr = ParseUnaryExpression();
560 if (!expr)
561 return nullptr;
562
563 expr = pdfium::MakeUnique<CXFA_FMPosExpression>(line, std::move(expr));
564 break;
565 case TOKminus:
566 if (!NextToken())
567 return nullptr;
568
569 expr = ParseUnaryExpression();
570 if (!expr)
571 return nullptr;
572
573 expr = pdfium::MakeUnique<CXFA_FMNegExpression>(line, std::move(expr));
574 break;
575 case TOKksnot:
576 if (!NextToken())
577 return nullptr;
578
579 expr = ParseUnaryExpression();
580 if (!expr)
581 return nullptr;
582
583 expr = pdfium::MakeUnique<CXFA_FMNotExpression>(line, std::move(expr));
584 break;
585 default:
586 expr = ParsePrimaryExpression();
587 if (!expr)
588 return nullptr;
589 break;
590 }
591 return expr;
592 }
593
594 std::unique_ptr<CXFA_FMSimpleExpression>
ParsePrimaryExpression()595 CXFA_FMParser::ParsePrimaryExpression() {
596 AutoRestorer<unsigned long> restorer(&m_parse_depth);
597 if (HasError() || !IncrementParseDepthAndCheck())
598 return nullptr;
599
600 std::unique_ptr<CXFA_FMSimpleExpression> expr;
601 uint32_t line = m_token->m_line_num;
602 switch (m_token->m_type) {
603 case TOKnumber:
604 expr =
605 pdfium::MakeUnique<CXFA_FMNumberExpression>(line, m_token->m_string);
606 if (!NextToken())
607 return nullptr;
608 break;
609 case TOKstring:
610 expr =
611 pdfium::MakeUnique<CXFA_FMStringExpression>(line, m_token->m_string);
612 if (!NextToken())
613 return nullptr;
614 break;
615 case TOKidentifier: {
616 WideStringView wsIdentifier(m_token->m_string);
617 if (!NextToken())
618 return nullptr;
619 if (m_token->m_type == TOKlbracket) {
620 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
621 if (!s)
622 return nullptr;
623
624 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
625 line, nullptr, TOKdot, wsIdentifier, std::move(s));
626 if (!expr)
627 return nullptr;
628 if (!NextToken())
629 return nullptr;
630 } else {
631 expr =
632 pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line, wsIdentifier);
633 }
634 break;
635 }
636 case TOKif:
637 expr = pdfium::MakeUnique<CXFA_FMIdentifierExpression>(line,
638 m_token->m_string);
639 if (!expr || !NextToken())
640 return nullptr;
641 break;
642 case TOKnull:
643 expr = pdfium::MakeUnique<CXFA_FMNullExpression>(line);
644 if (!expr || !NextToken())
645 return nullptr;
646 break;
647 case TOKlparen:
648 expr = ParseParenExpression();
649 if (!expr)
650 return nullptr;
651 break;
652 default:
653 m_error = true;
654 return nullptr;
655 }
656 expr = ParsePostExpression(std::move(expr));
657 if (!expr)
658 return nullptr;
659 return expr;
660 }
661
ParsePostExpression(std::unique_ptr<CXFA_FMSimpleExpression> expr)662 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParsePostExpression(
663 std::unique_ptr<CXFA_FMSimpleExpression> expr) {
664 AutoRestorer<unsigned long> restorer(&m_parse_depth);
665 if (HasError() || !IncrementParseDepthAndCheck())
666 return nullptr;
667
668 if (HasError())
669 return nullptr;
670
671 uint32_t line = m_token->m_line_num;
672 while (1) {
673 switch (m_token->m_type) {
674 case TOKlparen: {
675 if (!NextToken())
676 return nullptr;
677 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions;
678 if (m_token->m_type != TOKrparen) {
679 while (m_token->m_type != TOKrparen) {
680 std::unique_ptr<CXFA_FMSimpleExpression> simple_expr =
681 ParseSimpleExpression();
682 if (!simple_expr)
683 return nullptr;
684
685 expressions.push_back(std::move(simple_expr));
686 if (m_token->m_type == TOKcomma) {
687 if (!NextToken())
688 return nullptr;
689 } else if (m_token->m_type == TOKeof ||
690 m_token->m_type == TOKreserver) {
691 break;
692 }
693 }
694 if (m_token->m_type != TOKrparen) {
695 m_error = true;
696 return nullptr;
697 }
698 }
699 expr = pdfium::MakeUnique<CXFA_FMCallExpression>(
700 line, std::move(expr), std::move(expressions), false);
701 if (!NextToken())
702 return nullptr;
703 if (m_token->m_type != TOKlbracket)
704 continue;
705
706 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
707 if (!s)
708 return nullptr;
709
710 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
711 line, std::move(expr), TOKcall, L"", std::move(s));
712 break;
713 }
714 case TOKdot: {
715 if (!NextToken())
716 return nullptr;
717 if (m_token->m_type != TOKidentifier) {
718 m_error = true;
719 return nullptr;
720 }
721 WideStringView tempStr = m_token->m_string;
722 uint32_t tempLine = m_token->m_line_num;
723 if (!NextToken())
724 return nullptr;
725 if (m_token->m_type == TOKlparen) {
726 std::unique_ptr<CXFA_FMSimpleExpression> pExpCall;
727 if (!NextToken())
728 return nullptr;
729
730 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> expressions;
731 if (m_token->m_type != TOKrparen) {
732 while (m_token->m_type != TOKrparen) {
733 std::unique_ptr<CXFA_FMSimpleExpression> exp =
734 ParseSimpleExpression();
735 if (!exp)
736 return nullptr;
737
738 expressions.push_back(std::move(exp));
739 if (m_token->m_type == TOKcomma) {
740 if (!NextToken())
741 return nullptr;
742 } else if (m_token->m_type == TOKeof ||
743 m_token->m_type == TOKreserver) {
744 break;
745 }
746 }
747 if (m_token->m_type != TOKrparen) {
748 m_error = true;
749 return nullptr;
750 }
751 }
752 std::unique_ptr<CXFA_FMSimpleExpression> pIdentifier =
753 pdfium::MakeUnique<CXFA_FMIdentifierExpression>(tempLine,
754 tempStr);
755 pExpCall = pdfium::MakeUnique<CXFA_FMCallExpression>(
756 line, std::move(pIdentifier), std::move(expressions), true);
757 expr = pdfium::MakeUnique<CXFA_FMMethodCallExpression>(
758 line, std::move(expr), std::move(pExpCall));
759 if (!NextToken())
760 return nullptr;
761 if (m_token->m_type != TOKlbracket)
762 continue;
763
764 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
765 if (!s)
766 return nullptr;
767
768 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
769 line, std::move(expr), TOKcall, L"", std::move(s));
770 } else if (m_token->m_type == TOKlbracket) {
771 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
772 if (!s)
773 return nullptr;
774
775 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
776 tempLine, std::move(expr), TOKdot, tempStr, std::move(s));
777 } else {
778 std::unique_ptr<CXFA_FMSimpleExpression> s =
779 pdfium::MakeUnique<CXFA_FMIndexExpression>(
780 tempLine, ACCESSOR_NO_INDEX, nullptr, false);
781 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
782 line, std::move(expr), TOKdot, tempStr, std::move(s));
783 continue;
784 }
785 } break;
786 case TOKdotdot: {
787 if (!NextToken())
788 return nullptr;
789 if (m_token->m_type != TOKidentifier) {
790 m_error = true;
791 return nullptr;
792 }
793 WideStringView tempStr = m_token->m_string;
794 uint32_t tempLine = m_token->m_line_num;
795 if (!NextToken())
796 return nullptr;
797 if (m_token->m_type == TOKlbracket) {
798 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
799 if (!s)
800 return nullptr;
801
802 expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
803 tempLine, std::move(expr), TOKdotdot, tempStr, std::move(s));
804 } else {
805 std::unique_ptr<CXFA_FMSimpleExpression> s =
806 pdfium::MakeUnique<CXFA_FMIndexExpression>(
807 tempLine, ACCESSOR_NO_INDEX, nullptr, false);
808 expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
809 line, std::move(expr), TOKdotdot, tempStr, std::move(s));
810 continue;
811 }
812 } break;
813 case TOKdotscream: {
814 if (!NextToken())
815 return nullptr;
816 if (m_token->m_type != TOKidentifier) {
817 m_error = true;
818 return nullptr;
819 }
820 WideStringView tempStr = m_token->m_string;
821 uint32_t tempLine = m_token->m_line_num;
822 if (!NextToken())
823 return nullptr;
824 if (m_token->m_type != TOKlbracket) {
825 std::unique_ptr<CXFA_FMSimpleExpression> s =
826 pdfium::MakeUnique<CXFA_FMIndexExpression>(
827 tempLine, ACCESSOR_NO_INDEX, nullptr, false);
828 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
829 line, std::move(expr), TOKdotscream, tempStr, std::move(s));
830 continue;
831 }
832 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
833 if (!s)
834 return nullptr;
835
836 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
837 tempLine, std::move(expr), TOKdotscream, tempStr, std::move(s));
838 break;
839 }
840 case TOKdotstar: {
841 std::unique_ptr<CXFA_FMSimpleExpression> s =
842 pdfium::MakeUnique<CXFA_FMIndexExpression>(line, ACCESSOR_NO_INDEX,
843 nullptr, false);
844 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
845 line, std::move(expr), TOKdotstar, L"*", std::move(s));
846 break;
847 }
848 default:
849 return expr;
850 }
851 if (!NextToken())
852 return nullptr;
853 }
854 return expr;
855 }
856
ParseIndexExpression()857 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseIndexExpression() {
858 AutoRestorer<unsigned long> restorer(&m_parse_depth);
859 if (HasError() || !IncrementParseDepthAndCheck())
860 return nullptr;
861
862 uint32_t line = m_token->m_line_num;
863 if (!NextToken())
864 return nullptr;
865
866 std::unique_ptr<CXFA_FMSimpleExpression> s;
867 XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX;
868 std::unique_ptr<CXFA_FMSimpleExpression> pExp;
869 if (m_token->m_type == TOKmul) {
870 pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex,
871 std::move(s), true);
872 if (!pExp || !NextToken())
873 return nullptr;
874 if (m_token->m_type != TOKrbracket) {
875 m_error = true;
876 return nullptr;
877 }
878 return pExp;
879 }
880 if (m_token->m_type == TOKplus) {
881 accessorIndex = ACCESSOR_POSITIVE_INDEX;
882 if (!NextToken())
883 return nullptr;
884 } else if (m_token->m_type == TOKminus) {
885 accessorIndex = ACCESSOR_NEGATIVE_INDEX;
886 if (!NextToken())
887 return nullptr;
888 }
889 s = ParseSimpleExpression();
890 if (!s)
891 return nullptr;
892 if (m_token->m_type != TOKrbracket) {
893 m_error = true;
894 return nullptr;
895 }
896 return pdfium::MakeUnique<CXFA_FMIndexExpression>(line, accessorIndex,
897 std::move(s), false);
898 }
899
ParseParenExpression()900 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseParenExpression() {
901 AutoRestorer<unsigned long> restorer(&m_parse_depth);
902 if (HasError() || !IncrementParseDepthAndCheck())
903 return nullptr;
904
905 if (!CheckThenNext(TOKlparen))
906 return nullptr;
907
908 if (m_token->m_type == TOKrparen) {
909 m_error = true;
910 return nullptr;
911 }
912
913 uint32_t line = m_token->m_line_num;
914 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseLogicalOrExpression();
915 if (!pExp1)
916 return nullptr;
917
918 int level = 1;
919 while (m_token->m_type == TOKassign) {
920 if (!NextToken())
921 return nullptr;
922
923 std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseLogicalOrExpression();
924 if (!pExp2)
925 return nullptr;
926 if (level++ == kMaxAssignmentChainLength) {
927 m_error = true;
928 return nullptr;
929 }
930
931 pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>(
932 line, TOKassign, std::move(pExp1), std::move(pExp2));
933 }
934 if (!CheckThenNext(TOKrparen))
935 return nullptr;
936 return pExp1;
937 }
938
ParseBlockExpression()939 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseBlockExpression() {
940 AutoRestorer<unsigned long> restorer(&m_parse_depth);
941 if (HasError() || !IncrementParseDepthAndCheck())
942 return nullptr;
943
944 if (HasError())
945 return nullptr;
946
947 uint32_t line = m_token->m_line_num;
948 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
949 while (1) {
950 std::unique_ptr<CXFA_FMExpression> expr;
951 switch (m_token->m_type) {
952 case TOKeof:
953 case TOKendif:
954 case TOKelseif:
955 case TOKelse:
956 case TOKendwhile:
957 case TOKendfor:
958 case TOKend:
959 case TOKendfunc:
960 case TOKreserver:
961 break;
962 case TOKfunc:
963 expr = ParseFunction();
964 if (!expr)
965 return nullptr;
966
967 expressions.push_back(std::move(expr));
968 continue;
969 default:
970 expr = ParseExpression();
971 if (!expr)
972 return nullptr;
973
974 expressions.push_back(std::move(expr));
975 continue;
976 }
977 break;
978 }
979 return pdfium::MakeUnique<CXFA_FMBlockExpression>(line,
980 std::move(expressions));
981 }
982
ParseIfExpression()983 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseIfExpression() {
984 AutoRestorer<unsigned long> restorer(&m_parse_depth);
985 if (HasError() || !IncrementParseDepthAndCheck())
986 return nullptr;
987
988 uint32_t line = m_token->m_line_num;
989 const wchar_t* pStartPos = m_lexer->GetPos();
990 if (!NextToken() || !CheckThenNext(TOKlparen))
991 return nullptr;
992
993 std::unique_ptr<CXFA_FMSimpleExpression> pExpression;
994 while (m_token->m_type != TOKrparen) {
995 pExpression = ParseSimpleExpression();
996 if (!pExpression)
997 return nullptr;
998 if (m_token->m_type != TOKcomma)
999 break;
1000 if (!NextToken())
1001 return nullptr;
1002 }
1003 if (!CheckThenNext(TOKrparen))
1004 return nullptr;
1005 if (m_token->m_type != TOKthen) {
1006 m_lexer->SetCurrentLine(line);
1007 auto pNewToken = pdfium::MakeUnique<CXFA_FMToken>(line);
1008 m_token = std::move(pNewToken);
1009 m_token->m_type = TOKidentifier;
1010 m_token->m_string = L"if";
1011 m_lexer->SetPos(pStartPos);
1012 return ParseExpExpression();
1013 }
1014 if (!CheckThenNext(TOKthen))
1015 return nullptr;
1016
1017 std::unique_ptr<CXFA_FMExpression> pIfExpression = ParseBlockExpression();
1018 if (!pIfExpression)
1019 return nullptr;
1020
1021 std::unique_ptr<CXFA_FMExpression> pElseExpression;
1022 switch (m_token->m_type) {
1023 case TOKeof:
1024 case TOKendif:
1025 if (!CheckThenNext(TOKendif))
1026 return nullptr;
1027 break;
1028 case TOKif:
1029 pElseExpression = ParseIfExpression();
1030 if (!pElseExpression || !CheckThenNext(TOKendif))
1031 return nullptr;
1032 break;
1033 case TOKelseif:
1034 pElseExpression = ParseIfExpression();
1035 if (!pElseExpression)
1036 return nullptr;
1037 break;
1038 case TOKelse:
1039 if (!NextToken())
1040 return nullptr;
1041 pElseExpression = ParseBlockExpression();
1042 if (!pElseExpression || !CheckThenNext(TOKendif))
1043 return nullptr;
1044 break;
1045 default:
1046 m_error = true;
1047 return nullptr;
1048 }
1049 return pdfium::MakeUnique<CXFA_FMIfExpression>(line, std::move(pExpression),
1050 std::move(pIfExpression),
1051 std::move(pElseExpression));
1052 }
1053
ParseWhileExpression()1054 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseWhileExpression() {
1055 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1056 if (HasError() || !IncrementParseDepthAndCheck())
1057 return nullptr;
1058
1059 uint32_t line = m_token->m_line_num;
1060 if (!NextToken())
1061 return nullptr;
1062
1063 std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression();
1064 if (!pCondition || !CheckThenNext(TOKdo))
1065 return nullptr;
1066
1067 std::unique_ptr<CXFA_FMExpression> pExpression = ParseBlockExpression();
1068 if (!pExpression || !CheckThenNext(TOKendwhile))
1069 return nullptr;
1070 return pdfium::MakeUnique<CXFA_FMWhileExpression>(line, std::move(pCondition),
1071 std::move(pExpression));
1072 }
1073
1074 std::unique_ptr<CXFA_FMSimpleExpression>
ParseSubassignmentInForExpression()1075 CXFA_FMParser::ParseSubassignmentInForExpression() {
1076 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1077 if (HasError() || !IncrementParseDepthAndCheck())
1078 return nullptr;
1079
1080 if (HasError())
1081 return nullptr;
1082
1083 if (m_token->m_type != TOKidentifier) {
1084 m_error = true;
1085 return nullptr;
1086 }
1087 std::unique_ptr<CXFA_FMSimpleExpression> expr = ParseSimpleExpression();
1088 if (!expr)
1089 return nullptr;
1090 return expr;
1091 }
1092
ParseForExpression()1093 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseForExpression() {
1094 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1095 if (HasError() || !IncrementParseDepthAndCheck())
1096 return nullptr;
1097
1098 WideStringView wsVariant;
1099 uint32_t line = m_token->m_line_num;
1100 if (!NextToken())
1101 return nullptr;
1102 if (m_token->m_type != TOKidentifier) {
1103 m_error = true;
1104 return nullptr;
1105 }
1106
1107 wsVariant = m_token->m_string;
1108 if (!NextToken())
1109 return nullptr;
1110 if (m_token->m_type != TOKassign) {
1111 m_error = true;
1112 return nullptr;
1113 }
1114 if (!NextToken())
1115 return nullptr;
1116
1117 std::unique_ptr<CXFA_FMSimpleExpression> pAssignment =
1118 ParseSimpleExpression();
1119 if (!pAssignment)
1120 return nullptr;
1121
1122 int32_t iDirection = 0;
1123 if (m_token->m_type == TOKupto) {
1124 iDirection = 1;
1125 } else if (m_token->m_type == TOKdownto) {
1126 iDirection = -1;
1127 } else {
1128 m_error = true;
1129 return nullptr;
1130 }
1131
1132 if (!NextToken())
1133 return nullptr;
1134
1135 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor = ParseSimpleExpression();
1136 if (!pAccessor)
1137 return nullptr;
1138
1139 std::unique_ptr<CXFA_FMSimpleExpression> pStep;
1140 if (m_token->m_type == TOKstep) {
1141 if (!NextToken())
1142 return nullptr;
1143 pStep = ParseSimpleExpression();
1144 if (!pStep)
1145 return nullptr;
1146 }
1147 if (!CheckThenNext(TOKdo))
1148 return nullptr;
1149
1150 std::unique_ptr<CXFA_FMExpression> pList = ParseBlockExpression();
1151 if (!pList || !CheckThenNext(TOKendfor))
1152 return nullptr;
1153
1154 std::unique_ptr<CXFA_FMExpression> expr;
1155 if (!expr)
1156 return nullptr;
1157 return pdfium::MakeUnique<CXFA_FMForExpression>(
1158 line, wsVariant, std::move(pAssignment), std::move(pAccessor), iDirection,
1159 std::move(pStep), std::move(pList));
1160 }
1161
ParseForeachExpression()1162 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseForeachExpression() {
1163 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1164 if (HasError() || !IncrementParseDepthAndCheck())
1165 return nullptr;
1166
1167 if (HasError())
1168 return nullptr;
1169
1170 std::unique_ptr<CXFA_FMExpression> expr;
1171 WideStringView wsIdentifier;
1172 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> pAccessors;
1173 std::unique_ptr<CXFA_FMExpression> pList;
1174 uint32_t line = m_token->m_line_num;
1175 if (!NextToken())
1176 return nullptr;
1177 if (m_token->m_type != TOKidentifier) {
1178 m_error = true;
1179 return nullptr;
1180 }
1181
1182 wsIdentifier = m_token->m_string;
1183 if (!NextToken() || !CheckThenNext(TOKin) || !CheckThenNext(TOKlparen))
1184 return nullptr;
1185 if (m_token->m_type == TOKrparen) {
1186 m_error = true;
1187 return nullptr;
1188 }
1189
1190 while (m_token->m_type != TOKrparen) {
1191 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression();
1192 if (!s)
1193 return nullptr;
1194
1195 pAccessors.push_back(std::move(s));
1196 if (m_token->m_type != TOKcomma)
1197 break;
1198 if (!NextToken())
1199 return nullptr;
1200 }
1201 if (!CheckThenNext(TOKrparen) || !CheckThenNext(TOKdo))
1202 return nullptr;
1203
1204 pList = ParseBlockExpression();
1205 if (!pList || !CheckThenNext(TOKendfor))
1206 return nullptr;
1207 return pdfium::MakeUnique<CXFA_FMForeachExpression>(
1208 line, wsIdentifier, std::move(pAccessors), std::move(pList));
1209 }
1210
ParseDoExpression()1211 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseDoExpression() {
1212 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1213 if (HasError() || !IncrementParseDepthAndCheck())
1214 return nullptr;
1215
1216 if (HasError())
1217 return nullptr;
1218
1219 uint32_t line = m_token->m_line_num;
1220 if (!NextToken())
1221 return nullptr;
1222
1223 std::unique_ptr<CXFA_FMExpression> expr = ParseBlockExpression();
1224 if (!expr || !CheckThenNext(TOKend))
1225 return nullptr;
1226 return pdfium::MakeUnique<CXFA_FMDoExpression>(line, std::move(expr));
1227 }
1228
HasError() const1229 bool CXFA_FMParser::HasError() const {
1230 return m_error || m_token == nullptr;
1231 }
1232