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 constexpr unsigned int kMaxParseDepth = 1250;
19 constexpr unsigned int kMaxPostExpressions = 256;
20 constexpr unsigned int kMaxExpressionListSize = 10000;
21
22 } // namespace
23
CXFA_FMParser(WideStringView wsFormcalc)24 CXFA_FMParser::CXFA_FMParser(WideStringView wsFormcalc)
25 : m_lexer(pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc)),
26 m_error(false),
27 m_parse_depth(0),
28 m_max_parse_depth(kMaxParseDepth) {}
29
30 CXFA_FMParser::~CXFA_FMParser() = default;
31
Parse()32 std::unique_ptr<CXFA_FMAST> CXFA_FMParser::Parse() {
33 m_token = m_lexer->NextToken();
34 if (HasError())
35 return nullptr;
36
37 auto expressions = ParseExpressionList();
38 if (HasError())
39 return nullptr;
40
41 // We failed to parse all of the input so something has gone wrong.
42 if (!m_lexer->IsComplete())
43 return nullptr;
44
45 return pdfium::MakeUnique<CXFA_FMAST>(std::move(expressions));
46 }
47
NextToken()48 bool CXFA_FMParser::NextToken() {
49 if (HasError())
50 return false;
51
52 m_token = m_lexer->NextToken();
53 while (!HasError() && m_token.m_type == TOKreserver)
54 m_token = m_lexer->NextToken();
55 return !HasError();
56 }
57
CheckThenNext(XFA_FM_TOKEN op)58 bool CXFA_FMParser::CheckThenNext(XFA_FM_TOKEN op) {
59 if (HasError())
60 return false;
61
62 if (m_token.m_type != op) {
63 m_error = true;
64 return false;
65 }
66 return NextToken();
67 }
68
IncrementParseDepthAndCheck()69 bool CXFA_FMParser::IncrementParseDepthAndCheck() {
70 return ++m_parse_depth < m_max_parse_depth;
71 }
72
73 std::vector<std::unique_ptr<CXFA_FMExpression>>
ParseExpressionList()74 CXFA_FMParser::ParseExpressionList() {
75 AutoRestorer<unsigned long> restorer(&m_parse_depth);
76 if (HasError() || !IncrementParseDepthAndCheck())
77 return std::vector<std::unique_ptr<CXFA_FMExpression>>();
78
79 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
80 while (!HasError()) {
81 if (m_token.m_type == TOKeof || m_token.m_type == TOKendfunc ||
82 m_token.m_type == TOKendif || m_token.m_type == TOKelseif ||
83 m_token.m_type == TOKelse || m_token.m_type == TOKendwhile ||
84 m_token.m_type == TOKendfor || m_token.m_type == TOKend ||
85 m_token.m_type == TOKendfunc || m_token.m_type == TOKreserver) {
86 break;
87 }
88
89 std::unique_ptr<CXFA_FMExpression> expr =
90 m_token.m_type == TOKfunc ? ParseFunction() : ParseExpression();
91 if (!expr) {
92 m_error = true;
93 return std::vector<std::unique_ptr<CXFA_FMExpression>>();
94 }
95
96 if (expressions.size() >= kMaxExpressionListSize) {
97 m_error = true;
98 return std::vector<std::unique_ptr<CXFA_FMExpression>>();
99 }
100
101 expressions.push_back(std::move(expr));
102 }
103 return expressions;
104 }
105
106 // Func := 'func' Identifier '(' ParameterList ')' do ExpressionList 'endfunc'
107 // ParamterList := (Not actually defined in the grammar) .....
108 // (Identifier (',' Identifier)*)?
ParseFunction()109 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseFunction() {
110 AutoRestorer<unsigned long> restorer(&m_parse_depth);
111 if (HasError() || !IncrementParseDepthAndCheck())
112 return nullptr;
113 if (!CheckThenNext(TOKfunc))
114 return nullptr;
115 if (m_token.m_type != TOKidentifier)
116 return nullptr;
117
118 WideStringView ident = m_token.m_string;
119 if (!NextToken())
120 return nullptr;
121 if (!CheckThenNext(TOKlparen))
122 return nullptr;
123
124 std::vector<WideStringView> arguments;
125 bool last_was_comma = false;
126 while (1) {
127 if (m_token.m_type == TOKrparen)
128 break;
129 if (m_token.m_type != TOKidentifier)
130 return nullptr;
131
132 last_was_comma = false;
133
134 arguments.push_back(m_token.m_string);
135 if (!NextToken())
136 return nullptr;
137 if (m_token.m_type != TOKcomma)
138 continue;
139
140 last_was_comma = true;
141 if (!NextToken())
142 return nullptr;
143 }
144 if (last_was_comma || !CheckThenNext(TOKrparen))
145 return nullptr;
146 if (!CheckThenNext(TOKdo))
147 return nullptr;
148
149 std::vector<std::unique_ptr<CXFA_FMExpression>> expressions;
150 if (m_token.m_type != TOKendfunc)
151 expressions = ParseExpressionList();
152
153 if (!CheckThenNext(TOKendfunc))
154 return nullptr;
155
156 return pdfium::MakeUnique<CXFA_FMFunctionDefinition>(
157 ident, std::move(arguments), std::move(expressions));
158 }
159
160 // Expression := IfExpression | WhileExpression | ForExpression |
161 // ForEachExpression | AssignmentExpression |
162 // DeclarationExpression | SimpleExpression
ParseExpression()163 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpression() {
164 AutoRestorer<unsigned long> restorer(&m_parse_depth);
165 if (HasError() || !IncrementParseDepthAndCheck())
166 return nullptr;
167
168 std::unique_ptr<CXFA_FMExpression> expr;
169 switch (m_token.m_type) {
170 case TOKvar:
171 expr = ParseDeclarationExpression();
172 break;
173 case TOKnull:
174 case TOKnumber:
175 case TOKstring:
176 case TOKplus:
177 case TOKminus:
178 case TOKksnot:
179 case TOKidentifier:
180 case TOKlparen:
181 expr = ParseExpExpression();
182 break;
183 case TOKif:
184 expr = ParseIfExpression();
185 break;
186 case TOKwhile:
187 expr = ParseWhileExpression();
188 break;
189 case TOKfor:
190 expr = ParseForExpression();
191 break;
192 case TOKforeach:
193 expr = ParseForeachExpression();
194 break;
195 case TOKdo:
196 expr = ParseDoExpression();
197 break;
198 case TOKbreak:
199 expr = pdfium::MakeUnique<CXFA_FMBreakExpression>();
200 if (!NextToken())
201 return nullptr;
202 break;
203 case TOKcontinue:
204 expr = pdfium::MakeUnique<CXFA_FMContinueExpression>();
205 if (!NextToken())
206 return nullptr;
207 break;
208 default:
209 return nullptr;
210 }
211 return expr;
212 }
213
214 // Declaration := 'var' Variable | 'var' Variable '=' SimpleExpression |
215 // 'Func' Identifier '(' ParameterList ')' do ExpressionList 'EndFunc'
216 // TODO(dsinclair): We appear to be handling the 'func' case elsewhere.
ParseDeclarationExpression()217 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseDeclarationExpression() {
218 AutoRestorer<unsigned long> restorer(&m_parse_depth);
219 if (HasError() || !IncrementParseDepthAndCheck())
220 return nullptr;
221
222 WideStringView ident;
223 if (!NextToken())
224 return nullptr;
225 if (m_token.m_type != TOKidentifier)
226 return nullptr;
227
228 ident = m_token.m_string;
229 if (!NextToken())
230 return nullptr;
231
232 std::unique_ptr<CXFA_FMSimpleExpression> expr;
233 if (m_token.m_type == TOKassign) {
234 if (!NextToken())
235 return nullptr;
236
237 expr = ParseSimpleExpression();
238 if (!expr)
239 return nullptr;
240 }
241
242 return pdfium::MakeUnique<CXFA_FMVarExpression>(ident, std::move(expr));
243 }
244
245 // SimpleExpression := LogicalOrExpression
246 std::unique_ptr<CXFA_FMSimpleExpression>
ParseSimpleExpression()247 CXFA_FMParser::ParseSimpleExpression() {
248 if (HasError())
249 return nullptr;
250
251 return ParseLogicalOrExpression();
252 }
253
254 // Exp := SimpleExpression ( '=' SimpleExpression )?
ParseExpExpression()255 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpExpression() {
256 AutoRestorer<unsigned long> restorer(&m_parse_depth);
257 if (HasError() || !IncrementParseDepthAndCheck())
258 return nullptr;
259
260 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression();
261 if (!pExp1)
262 return nullptr;
263
264 if (m_token.m_type == TOKassign) {
265 if (!NextToken())
266 return nullptr;
267
268 std::unique_ptr<CXFA_FMSimpleExpression> pExp2 = ParseSimpleExpression();
269 if (!pExp2)
270 return nullptr;
271
272 pExp1 = pdfium::MakeUnique<CXFA_FMAssignExpression>(
273 TOKassign, std::move(pExp1), std::move(pExp2));
274 }
275 return pdfium::MakeUnique<CXFA_FMExpExpression>(std::move(pExp1));
276 }
277
278 // LogicalOr := LogicalAndExpression |
279 // LogicalOrExpression LogicalOrOperator LogicalAndExpression
280 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalOrExpression()281 CXFA_FMParser::ParseLogicalOrExpression() {
282 AutoRestorer<unsigned long> restorer(&m_parse_depth);
283 if (HasError() || !IncrementParseDepthAndCheck())
284 return nullptr;
285
286 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseLogicalAndExpression();
287 if (!e1)
288 return nullptr;
289
290 // TODO(dsinclair): Is this for() needed?
291 for (;;) {
292 if (!IncrementParseDepthAndCheck())
293 return nullptr;
294
295 switch (m_token.m_type) {
296 case TOKor:
297 case TOKksor: {
298 if (!NextToken())
299 return nullptr;
300
301 std::unique_ptr<CXFA_FMSimpleExpression> e2(
302 ParseLogicalAndExpression());
303 if (!e2)
304 return nullptr;
305
306 e1 = pdfium::MakeUnique<CXFA_FMLogicalOrExpression>(
307 TOKor, std::move(e1), std::move(e2));
308 continue;
309 }
310 default:
311 break;
312 }
313 break;
314 }
315 return e1;
316 }
317
318 // LogicalAnd := EqualityExpression |
319 // LogicalAndExpression LogicalAndOperator EqualityExpression
320 std::unique_ptr<CXFA_FMSimpleExpression>
ParseLogicalAndExpression()321 CXFA_FMParser::ParseLogicalAndExpression() {
322 AutoRestorer<unsigned long> restorer(&m_parse_depth);
323 if (HasError() || !IncrementParseDepthAndCheck())
324 return nullptr;
325
326 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseEqualityExpression();
327 if (!e1)
328 return nullptr;
329
330 // TODO(dsinclair): Is this for() needed?
331 for (;;) {
332 if (!IncrementParseDepthAndCheck())
333 return nullptr;
334
335 switch (m_token.m_type) {
336 case TOKand:
337 case TOKksand: {
338 if (!NextToken())
339 return nullptr;
340
341 std::unique_ptr<CXFA_FMSimpleExpression> e2 = ParseEqualityExpression();
342 if (!e2)
343 return nullptr;
344
345 e1 = pdfium::MakeUnique<CXFA_FMLogicalAndExpression>(
346 TOKand, std::move(e1), std::move(e2));
347 continue;
348 }
349 default:
350 break;
351 }
352 break;
353 }
354 return e1;
355 }
356
357 // Equality := RelationExpression |
358 // EqualityExpression EqulaityOperator RelationalExpression
359 std::unique_ptr<CXFA_FMSimpleExpression>
ParseEqualityExpression()360 CXFA_FMParser::ParseEqualityExpression() {
361 AutoRestorer<unsigned long> restorer(&m_parse_depth);
362 if (HasError() || !IncrementParseDepthAndCheck())
363 return nullptr;
364
365 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseRelationalExpression();
366 if (!e1)
367 return nullptr;
368
369 // TODO(dsinclair): Is this for() needed?
370 for (;;) {
371 if (!IncrementParseDepthAndCheck())
372 return nullptr;
373
374 switch (m_token.m_type) {
375 case TOKeq:
376 case TOKkseq: {
377 if (!NextToken())
378 return nullptr;
379
380 std::unique_ptr<CXFA_FMSimpleExpression> e2 =
381 ParseRelationalExpression();
382 if (!e2)
383 return nullptr;
384
385 e1 = pdfium::MakeUnique<CXFA_FMEqualExpression>(TOKeq, std::move(e1),
386 std::move(e2));
387 continue;
388 }
389 case TOKne:
390 case TOKksne: {
391 if (!NextToken())
392 return nullptr;
393
394 std::unique_ptr<CXFA_FMSimpleExpression> e2 =
395 ParseRelationalExpression();
396 if (!e2)
397 return nullptr;
398
399 e1 = pdfium::MakeUnique<CXFA_FMNotEqualExpression>(TOKne, std::move(e1),
400 std::move(e2));
401 continue;
402 }
403 default:
404 break;
405 }
406 break;
407 }
408 return e1;
409 }
410
411 // Relational := AdditiveExpression |
412 // RelationalExpression RelationalOperator AdditiveExpression
413 std::unique_ptr<CXFA_FMSimpleExpression>
ParseRelationalExpression()414 CXFA_FMParser::ParseRelationalExpression() {
415 AutoRestorer<unsigned long> restorer(&m_parse_depth);
416 if (HasError() || !IncrementParseDepthAndCheck())
417 return nullptr;
418
419 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseAdditiveExpression();
420 if (!e1)
421 return nullptr;
422
423 // TODO(dsinclair): Is this for() needed?
424 for (;;) {
425 if (!IncrementParseDepthAndCheck())
426 return nullptr;
427
428 std::unique_ptr<CXFA_FMSimpleExpression> e2;
429 switch (m_token.m_type) {
430 case TOKlt:
431 case TOKkslt:
432 if (!NextToken())
433 return nullptr;
434
435 e2 = ParseAdditiveExpression();
436 if (!e2)
437 return nullptr;
438
439 e1 = pdfium::MakeUnique<CXFA_FMLtExpression>(TOKlt, std::move(e1),
440 std::move(e2));
441 continue;
442 case TOKgt:
443 case TOKksgt:
444 if (!NextToken())
445 return nullptr;
446
447 e2 = ParseAdditiveExpression();
448 if (!e2)
449 return nullptr;
450
451 e1 = pdfium::MakeUnique<CXFA_FMGtExpression>(TOKgt, std::move(e1),
452 std::move(e2));
453 continue;
454 case TOKle:
455 case TOKksle:
456 if (!NextToken())
457 return nullptr;
458
459 e2 = ParseAdditiveExpression();
460 if (!e2)
461 return nullptr;
462
463 e1 = pdfium::MakeUnique<CXFA_FMLeExpression>(TOKle, std::move(e1),
464 std::move(e2));
465 continue;
466 case TOKge:
467 case TOKksge:
468 if (!NextToken())
469 return nullptr;
470
471 e2 = ParseAdditiveExpression();
472 if (!e2)
473 return nullptr;
474
475 e1 = pdfium::MakeUnique<CXFA_FMGeExpression>(TOKge, std::move(e1),
476 std::move(e2));
477 continue;
478 default:
479 break;
480 }
481 break;
482 }
483 return e1;
484 }
485
486 // Additive := MultiplicativeExpression |
487 // AdditiveExpression AdditiveOperator MultiplicativeExpression
488 std::unique_ptr<CXFA_FMSimpleExpression>
ParseAdditiveExpression()489 CXFA_FMParser::ParseAdditiveExpression() {
490 AutoRestorer<unsigned long> restorer(&m_parse_depth);
491 if (HasError() || !IncrementParseDepthAndCheck())
492 return nullptr;
493
494 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseMultiplicativeExpression();
495 if (!e1)
496 return nullptr;
497
498 // TODO(dsinclair): Is this for() needed?
499 for (;;) {
500 if (!IncrementParseDepthAndCheck())
501 return nullptr;
502
503 std::unique_ptr<CXFA_FMSimpleExpression> e2;
504 switch (m_token.m_type) {
505 case TOKplus:
506 if (!NextToken())
507 return nullptr;
508
509 e2 = ParseMultiplicativeExpression();
510 if (!e2)
511 return nullptr;
512
513 e1 = pdfium::MakeUnique<CXFA_FMPlusExpression>(TOKplus, std::move(e1),
514 std::move(e2));
515 continue;
516 case TOKminus:
517 if (!NextToken())
518 return nullptr;
519
520 e2 = ParseMultiplicativeExpression();
521 if (!e2)
522 return nullptr;
523
524 e1 = pdfium::MakeUnique<CXFA_FMMinusExpression>(TOKminus, std::move(e1),
525 std::move(e2));
526 continue;
527 default:
528 break;
529 }
530 break;
531 }
532 return e1;
533 }
534
535 // Multiplicative := UnaryExpression |
536 // MultiplicateExpression MultiplicativeOperator UnaryExpression
537 std::unique_ptr<CXFA_FMSimpleExpression>
ParseMultiplicativeExpression()538 CXFA_FMParser::ParseMultiplicativeExpression() {
539 AutoRestorer<unsigned long> restorer(&m_parse_depth);
540 if (HasError() || !IncrementParseDepthAndCheck())
541 return nullptr;
542
543 std::unique_ptr<CXFA_FMSimpleExpression> e1 = ParseUnaryExpression();
544 if (!e1)
545 return nullptr;
546
547 // TODO(dsinclair): Is this for() needed?
548 for (;;) {
549 if (!IncrementParseDepthAndCheck())
550 return nullptr;
551
552 std::unique_ptr<CXFA_FMSimpleExpression> e2;
553 switch (m_token.m_type) {
554 case TOKmul:
555 if (!NextToken())
556 return nullptr;
557
558 e2 = ParseUnaryExpression();
559 if (!e2)
560 return nullptr;
561
562 e1 = pdfium::MakeUnique<CXFA_FMMulExpression>(TOKmul, std::move(e1),
563 std::move(e2));
564 continue;
565 case TOKdiv:
566 if (!NextToken())
567 return nullptr;
568
569 e2 = ParseUnaryExpression();
570 if (!e2)
571 return nullptr;
572
573 e1 = pdfium::MakeUnique<CXFA_FMDivExpression>(TOKdiv, std::move(e1),
574 std::move(e2));
575 continue;
576 default:
577 break;
578 }
579 break;
580 }
581 return e1;
582 }
583
584 // Unary := PrimaryExpression | UnaryOperator UnaryExpression
ParseUnaryExpression()585 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseUnaryExpression() {
586 AutoRestorer<unsigned long> restorer(&m_parse_depth);
587 if (HasError() || !IncrementParseDepthAndCheck())
588 return nullptr;
589
590 std::unique_ptr<CXFA_FMSimpleExpression> expr;
591 switch (m_token.m_type) {
592 case TOKplus:
593 if (!NextToken())
594 return nullptr;
595
596 expr = ParseUnaryExpression();
597 if (!expr)
598 return nullptr;
599
600 expr = pdfium::MakeUnique<CXFA_FMPosExpression>(std::move(expr));
601 break;
602 case TOKminus:
603 if (!NextToken())
604 return nullptr;
605
606 expr = ParseUnaryExpression();
607 if (!expr)
608 return nullptr;
609
610 expr = pdfium::MakeUnique<CXFA_FMNegExpression>(std::move(expr));
611 break;
612 case TOKksnot:
613 if (!NextToken())
614 return nullptr;
615
616 expr = ParseUnaryExpression();
617 if (!expr)
618 return nullptr;
619
620 expr = pdfium::MakeUnique<CXFA_FMNotExpression>(std::move(expr));
621 break;
622 default:
623 return ParsePrimaryExpression();
624 }
625 return expr;
626 }
627
628 // Primary := Literal | FunctionCall | Accessor ('.*' )? |
629 // '(' SimpleExpression ')'
630 std::unique_ptr<CXFA_FMSimpleExpression>
ParsePrimaryExpression()631 CXFA_FMParser::ParsePrimaryExpression() {
632 AutoRestorer<unsigned long> restorer(&m_parse_depth);
633 if (HasError() || !IncrementParseDepthAndCheck())
634 return nullptr;
635
636 std::unique_ptr<CXFA_FMSimpleExpression> expr = ParseLiteral();
637 if (expr)
638 return NextToken() ? std::move(expr) : nullptr;
639
640 switch (m_token.m_type) {
641 case TOKidentifier: {
642 WideStringView wsIdentifier(m_token.m_string);
643 if (!NextToken())
644 return nullptr;
645 if (m_token.m_type == TOKlbracket) {
646 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
647 if (!s)
648 return nullptr;
649
650 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
651 nullptr, TOKdot, wsIdentifier, std::move(s));
652 if (!expr)
653 return nullptr;
654 if (!NextToken())
655 return nullptr;
656 } else {
657 expr = pdfium::MakeUnique<CXFA_FMIdentifierExpression>(wsIdentifier);
658 }
659 break;
660 }
661 case TOKlparen:
662 expr = ParseParenExpression();
663 if (!expr)
664 return nullptr;
665 break;
666 default:
667 return nullptr;
668 }
669 return ParsePostExpression(std::move(expr));
670 }
671
672 // Literal := String | Number | Null
ParseLiteral()673 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseLiteral() {
674 switch (m_token.m_type) {
675 case TOKnumber:
676 return pdfium::MakeUnique<CXFA_FMNumberExpression>(m_token.m_string);
677 case TOKstring:
678 return pdfium::MakeUnique<CXFA_FMStringExpression>(m_token.m_string);
679 case TOKnull:
680 return pdfium::MakeUnique<CXFA_FMNullExpression>();
681 default:
682 return nullptr;
683 }
684 }
685
686 // TODO(dsinclair): Make this match up to the grammar
687 // I believe this is parsing the accessor ( '.' | '..' | '.#' )
ParsePostExpression(std::unique_ptr<CXFA_FMSimpleExpression> expr)688 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParsePostExpression(
689 std::unique_ptr<CXFA_FMSimpleExpression> expr) {
690 AutoRestorer<unsigned long> restorer(&m_parse_depth);
691 if (HasError() || !IncrementParseDepthAndCheck())
692 return nullptr;
693
694 size_t expr_count = 0;
695 while (1) {
696 ++expr_count;
697 // Limit the number of expressions allowed in the post expression statement.
698 // If we don't do this then its possible to generate a stack overflow
699 // by having a very large number of things like .. expressions.
700 if (expr_count > kMaxPostExpressions)
701 return nullptr;
702
703 switch (m_token.m_type) {
704 case TOKlparen: {
705 std::unique_ptr<std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>>
706 expressions = ParseArgumentList();
707 if (!expressions)
708 return nullptr;
709
710 expr = pdfium::MakeUnique<CXFA_FMCallExpression>(
711 std::move(expr), std::move(*expressions), false);
712 if (!NextToken())
713 return nullptr;
714 if (m_token.m_type != TOKlbracket)
715 continue;
716
717 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
718 if (!s)
719 return nullptr;
720
721 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
722 std::move(expr), TOKcall, WideStringView(), std::move(s));
723 break;
724 }
725 case TOKdot: {
726 if (!NextToken())
727 return nullptr;
728 if (m_token.m_type != TOKidentifier)
729 return nullptr;
730
731 WideStringView tempStr = m_token.m_string;
732 if (!NextToken())
733 return nullptr;
734 if (m_token.m_type == TOKlparen) {
735 std::unique_ptr<std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>>
736 expressions = ParseArgumentList();
737 if (!expressions)
738 return nullptr;
739
740 auto pIdentifier =
741 pdfium::MakeUnique<CXFA_FMIdentifierExpression>(tempStr);
742 auto pExpCall = pdfium::MakeUnique<CXFA_FMCallExpression>(
743 std::move(pIdentifier), std::move(*expressions), true);
744 expr = pdfium::MakeUnique<CXFA_FMMethodCallExpression>(
745 std::move(expr), std::move(pExpCall));
746 if (!NextToken())
747 return nullptr;
748 if (m_token.m_type != TOKlbracket)
749 continue;
750
751 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
752 if (!s)
753 return nullptr;
754
755 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
756 std::move(expr), TOKcall, WideStringView(), std::move(s));
757 } else if (m_token.m_type == TOKlbracket) {
758 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
759 if (!s)
760 return nullptr;
761
762 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
763 std::move(expr), TOKdot, tempStr, std::move(s));
764 } else {
765 std::unique_ptr<CXFA_FMSimpleExpression> s =
766 pdfium::MakeUnique<CXFA_FMIndexExpression>(ACCESSOR_NO_INDEX,
767 nullptr, false);
768 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
769 std::move(expr), TOKdot, tempStr, std::move(s));
770 continue;
771 }
772 break;
773 }
774 case TOKdotdot: {
775 if (!NextToken())
776 return nullptr;
777 if (m_token.m_type != TOKidentifier)
778 return nullptr;
779
780 WideStringView tempStr = m_token.m_string;
781 if (!NextToken())
782 return nullptr;
783 if (m_token.m_type == TOKlbracket) {
784 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
785 if (!s)
786 return nullptr;
787
788 expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
789 std::move(expr), TOKdotdot, tempStr, std::move(s));
790 } else {
791 std::unique_ptr<CXFA_FMSimpleExpression> s =
792 pdfium::MakeUnique<CXFA_FMIndexExpression>(ACCESSOR_NO_INDEX,
793 nullptr, false);
794 expr = pdfium::MakeUnique<CXFA_FMDotDotAccessorExpression>(
795 std::move(expr), TOKdotdot, tempStr, std::move(s));
796 continue;
797 }
798 break;
799 }
800 case TOKdotscream: {
801 if (!NextToken())
802 return nullptr;
803 if (m_token.m_type != TOKidentifier)
804 return nullptr;
805
806 WideStringView tempStr = m_token.m_string;
807 if (!NextToken())
808 return nullptr;
809
810 if (m_token.m_type != TOKlbracket) {
811 std::unique_ptr<CXFA_FMSimpleExpression> s =
812 pdfium::MakeUnique<CXFA_FMIndexExpression>(ACCESSOR_NO_INDEX,
813 nullptr, false);
814 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
815 std::move(expr), TOKdotscream, tempStr, std::move(s));
816 continue;
817 }
818
819 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseIndexExpression();
820 if (!s)
821 return nullptr;
822
823 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
824 std::move(expr), TOKdotscream, tempStr, std::move(s));
825 break;
826 }
827 case TOKdotstar: {
828 std::unique_ptr<CXFA_FMSimpleExpression> s =
829 pdfium::MakeUnique<CXFA_FMIndexExpression>(ACCESSOR_NO_INDEX,
830 nullptr, false);
831 expr = pdfium::MakeUnique<CXFA_FMDotAccessorExpression>(
832 std::move(expr), TOKdotstar, L"*", std::move(s));
833 break;
834 }
835 default:
836 return expr;
837 }
838 if (!NextToken())
839 return nullptr;
840 }
841 return expr;
842 }
843
844 // Argument lists are zero or more comma seperated simple expressions found
845 // between '(' and ')'
846 std::unique_ptr<std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>>
ParseArgumentList()847 CXFA_FMParser::ParseArgumentList() {
848 if (m_token.m_type != TOKlparen || !NextToken())
849 return nullptr;
850
851 auto expressions = pdfium::MakeUnique<
852 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>>();
853 bool first_arg = true;
854 while (m_token.m_type != TOKrparen) {
855 if (first_arg) {
856 first_arg = false;
857 } else {
858 if (m_token.m_type != TOKcomma || !NextToken())
859 return nullptr;
860 }
861
862 std::unique_ptr<CXFA_FMSimpleExpression> exp = ParseSimpleExpression();
863 if (!exp)
864 return nullptr;
865
866 expressions->push_back(std::move(exp));
867 if (expressions->size() > kMaxPostExpressions)
868 return nullptr;
869 }
870
871 return expressions;
872 }
873
874 // Index := '[' ('*' | '+' SimpleExpression | '-' SimpleExpression) ']'
ParseIndexExpression()875 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseIndexExpression() {
876 AutoRestorer<unsigned long> restorer(&m_parse_depth);
877 if (HasError() || !IncrementParseDepthAndCheck())
878 return nullptr;
879 if (!CheckThenNext(TOKlbracket))
880 return nullptr;
881
882 if (m_token.m_type == TOKmul) {
883 auto pExp = pdfium::MakeUnique<CXFA_FMIndexExpression>(
884 ACCESSOR_NO_RELATIVEINDEX, nullptr, true);
885 if (!pExp || !NextToken())
886 return nullptr;
887
888 // TODO(dsinclair): This should CheckThenNext(TOKrbracket) but need to clean
889 // up the callsites.
890 if (m_token.m_type != TOKrbracket)
891 return nullptr;
892 return pExp;
893 }
894
895 XFA_FM_AccessorIndex accessorIndex = ACCESSOR_NO_RELATIVEINDEX;
896 if (m_token.m_type == TOKplus) {
897 accessorIndex = ACCESSOR_POSITIVE_INDEX;
898 if (!NextToken())
899 return nullptr;
900 } else if (m_token.m_type == TOKminus) {
901 accessorIndex = ACCESSOR_NEGATIVE_INDEX;
902 if (!NextToken())
903 return nullptr;
904 }
905
906 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression();
907 if (!s)
908 return nullptr;
909 if (m_token.m_type != TOKrbracket)
910 return nullptr;
911
912 return pdfium::MakeUnique<CXFA_FMIndexExpression>(accessorIndex, std::move(s),
913 false);
914 }
915
916 // Paren := '(' SimpleExpression ')'
ParseParenExpression()917 std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseParenExpression() {
918 AutoRestorer<unsigned long> restorer(&m_parse_depth);
919 if (HasError() || !IncrementParseDepthAndCheck())
920 return nullptr;
921
922 if (!CheckThenNext(TOKlparen))
923 return nullptr;
924 if (m_token.m_type == TOKrparen)
925 return nullptr;
926
927 std::unique_ptr<CXFA_FMSimpleExpression> pExp1 = ParseSimpleExpression();
928 if (!pExp1)
929 return nullptr;
930
931 if (!CheckThenNext(TOKrparen))
932 return nullptr;
933 return pExp1;
934 }
935
936 // If := 'if' '(' SimpleExpression ')' 'then' ExpressionList
937 // ('elseif' '(' SimpleExpression ')' 'then' ExpressionList)*
938 // ('else' ExpressionList)?
939 // 'endif'
ParseIfExpression()940 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseIfExpression() {
941 AutoRestorer<unsigned long> restorer(&m_parse_depth);
942 if (HasError() || !IncrementParseDepthAndCheck())
943 return nullptr;
944
945 if (!CheckThenNext(TOKif))
946 return nullptr;
947
948 std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression();
949 if (!pCondition)
950 return nullptr;
951 if (!CheckThenNext(TOKthen))
952 return nullptr;
953
954 auto pIfExpressions =
955 pdfium::MakeUnique<CXFA_FMBlockExpression>(ParseExpressionList());
956
957 std::vector<std::unique_ptr<CXFA_FMIfExpression>> pElseIfExpressions;
958 while (m_token.m_type == TOKelseif) {
959 if (!NextToken())
960 return nullptr;
961
962 auto elseIfCondition = ParseParenExpression();
963 if (!elseIfCondition)
964 return nullptr;
965 if (!CheckThenNext(TOKthen))
966 return nullptr;
967
968 auto elseIfExprs = ParseExpressionList();
969 pElseIfExpressions.push_back(pdfium::MakeUnique<CXFA_FMIfExpression>(
970 std::move(elseIfCondition),
971 pdfium::MakeUnique<CXFA_FMBlockExpression>(std::move(elseIfExprs)),
972 std::vector<std::unique_ptr<CXFA_FMIfExpression>>(), nullptr));
973 }
974
975 std::unique_ptr<CXFA_FMExpression> pElseExpression;
976 if (m_token.m_type == TOKelse) {
977 if (!NextToken())
978 return nullptr;
979
980 pElseExpression =
981 pdfium::MakeUnique<CXFA_FMBlockExpression>(ParseExpressionList());
982 }
983 if (!CheckThenNext(TOKendif))
984 return nullptr;
985
986 return pdfium::MakeUnique<CXFA_FMIfExpression>(
987 std::move(pCondition), std::move(pIfExpressions),
988 std::move(pElseIfExpressions), std::move(pElseExpression));
989 }
990
991 // While := 'while' '(' SimpleExpression ')' 'do' ExpressionList 'endwhile'
ParseWhileExpression()992 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseWhileExpression() {
993 AutoRestorer<unsigned long> restorer(&m_parse_depth);
994 if (HasError() || !IncrementParseDepthAndCheck())
995 return nullptr;
996 if (!CheckThenNext(TOKwhile))
997 return nullptr;
998
999 std::unique_ptr<CXFA_FMSimpleExpression> pCondition = ParseParenExpression();
1000 if (!pCondition || !CheckThenNext(TOKdo))
1001 return nullptr;
1002
1003 auto exprs = ParseExpressionList();
1004 if (!CheckThenNext(TOKendwhile))
1005 return nullptr;
1006
1007 return pdfium::MakeUnique<CXFA_FMWhileExpression>(
1008 std::move(pCondition),
1009 pdfium::MakeUnique<CXFA_FMBlockExpression>(std::move(exprs)));
1010 }
1011
1012 // For := 'for' Assignment 'upto' Accessor ('step' SimpleExpression)?
1013 // 'do' ExpressionList 'endfor' |
1014 // 'for' Assignment 'downto' Accessor ('step' SimpleExpression)?
1015 // 'do' ExpressionList 'endfor'
ParseForExpression()1016 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseForExpression() {
1017 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1018 if (HasError() || !IncrementParseDepthAndCheck())
1019 return nullptr;
1020 if (!CheckThenNext(TOKfor))
1021 return nullptr;
1022 if (m_token.m_type != TOKidentifier)
1023 return nullptr;
1024
1025 WideStringView wsVariant = m_token.m_string;
1026 if (!NextToken())
1027 return nullptr;
1028 if (!CheckThenNext(TOKassign))
1029 return nullptr;
1030
1031 std::unique_ptr<CXFA_FMSimpleExpression> pAssignment =
1032 ParseSimpleExpression();
1033 if (!pAssignment)
1034 return nullptr;
1035
1036 int32_t iDirection = 0;
1037 if (m_token.m_type == TOKupto)
1038 iDirection = 1;
1039 else if (m_token.m_type == TOKdownto)
1040 iDirection = -1;
1041 else
1042 return nullptr;
1043
1044 if (!NextToken())
1045 return nullptr;
1046
1047 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor = ParseSimpleExpression();
1048 if (!pAccessor)
1049 return nullptr;
1050
1051 std::unique_ptr<CXFA_FMSimpleExpression> pStep;
1052 if (m_token.m_type == TOKstep) {
1053 if (!NextToken())
1054 return nullptr;
1055 pStep = ParseSimpleExpression();
1056 if (!pStep)
1057 return nullptr;
1058 }
1059 if (!CheckThenNext(TOKdo))
1060 return nullptr;
1061
1062 auto exprs = ParseExpressionList();
1063 if (!CheckThenNext(TOKendfor))
1064 return nullptr;
1065
1066 return pdfium::MakeUnique<CXFA_FMForExpression>(
1067 wsVariant, std::move(pAssignment), std::move(pAccessor), iDirection,
1068 std::move(pStep),
1069 pdfium::MakeUnique<CXFA_FMBlockExpression>(std::move(exprs)));
1070 }
1071
1072 // Foreach := 'foreach' Identifier 'in' '(' ArgumentList ')'
1073 // 'do' ExpressionList 'endfor'
ParseForeachExpression()1074 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseForeachExpression() {
1075 if (m_token.m_type != TOKforeach)
1076 return nullptr;
1077
1078 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1079 if (HasError() || !IncrementParseDepthAndCheck())
1080 return nullptr;
1081 if (!CheckThenNext(TOKforeach))
1082 return nullptr;
1083 if (m_token.m_type != TOKidentifier)
1084 return nullptr;
1085
1086 WideStringView wsIdentifier = m_token.m_string;
1087 if (!NextToken() || !CheckThenNext(TOKin) || !CheckThenNext(TOKlparen))
1088 return nullptr;
1089
1090 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> pArgumentList;
1091 while (m_token.m_type != TOKrparen) {
1092 std::unique_ptr<CXFA_FMSimpleExpression> s = ParseSimpleExpression();
1093 if (!s)
1094 return nullptr;
1095
1096 pArgumentList.push_back(std::move(s));
1097 if (m_token.m_type != TOKcomma)
1098 break;
1099 if (!NextToken())
1100 return nullptr;
1101 }
1102 // We must have arguments.
1103 if (pArgumentList.empty())
1104 return nullptr;
1105 if (!CheckThenNext(TOKrparen))
1106 return nullptr;
1107
1108 auto exprs = ParseExpressionList();
1109 if (!CheckThenNext(TOKendfor))
1110 return nullptr;
1111
1112 return pdfium::MakeUnique<CXFA_FMForeachExpression>(
1113 wsIdentifier, std::move(pArgumentList),
1114 pdfium::MakeUnique<CXFA_FMBlockExpression>(std::move(exprs)));
1115 }
1116
1117 // Block := 'do' ExpressionList 'end'
ParseDoExpression()1118 std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseDoExpression() {
1119 if (m_token.m_type != TOKdo)
1120 return nullptr;
1121
1122 AutoRestorer<unsigned long> restorer(&m_parse_depth);
1123 if (HasError() || !IncrementParseDepthAndCheck())
1124 return nullptr;
1125 if (!CheckThenNext(TOKdo))
1126 return nullptr;
1127
1128 auto exprs = ParseExpressionList();
1129 if (!CheckThenNext(TOKend))
1130 return nullptr;
1131
1132 return pdfium::MakeUnique<CXFA_FMDoExpression>(
1133 pdfium::MakeUnique<CXFA_FMBlockExpression>(std::move(exprs)));
1134 }
1135
HasError() const1136 bool CXFA_FMParser::HasError() const {
1137 return m_error || m_token.m_type == TOKreserver;
1138 }
1139