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