• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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