• 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_fmsimpleexpression.h"
8 
9 #include <algorithm>
10 #include <iostream>
11 #include <utility>
12 
13 #include "core/fxcrt/autorestorer.h"
14 #include "core/fxcrt/cfx_widetextbuf.h"
15 #include "core/fxcrt/fx_extension.h"
16 #include "third_party/base/logging.h"
17 #include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h"
18 
19 namespace {
20 
21 // Indexed by XFA_FM_SimpleExpressionType
22 const wchar_t* const gs_lpStrExpFuncName[] = {
23     L"pfm_rt.asgn_val_op", L"pfm_rt.log_or_op",  L"pfm_rt.log_and_op",
24     L"pfm_rt.eq_op",       L"pfm_rt.neq_op",     L"pfm_rt.lt_op",
25     L"pfm_rt.le_op",       L"pfm_rt.gt_op",      L"pfm_rt.ge_op",
26     L"pfm_rt.plus_op",     L"pfm_rt.minus_op",   L"pfm_rt.mul_op",
27     L"pfm_rt.div_op",      L"pfm_rt.pos_op",     L"pfm_rt.neg_op",
28     L"pfm_rt.log_not_op",  L"pfm_rt.",           L"pfm_rt.dot_acc",
29     L"pfm_rt.dotdot_acc",  L"pfm_rt.concat_obj", L"pfm_rt.is_obj",
30     L"pfm_rt.is_ary",      L"pfm_rt.get_val",    L"pfm_rt.get_jsobj",
31     L"pfm_rt.var_filter",
32 };
33 
34 const wchar_t* const g_BuiltInFuncs[] = {
35     L"Abs",          L"Apr",       L"At",       L"Avg",
36     L"Ceil",         L"Choose",    L"Concat",   L"Count",
37     L"Cterm",        L"Date",      L"Date2Num", L"DateFmt",
38     L"Decode",       L"Encode",    L"Eval",     L"Exists",
39     L"Floor",        L"Format",    L"FV",       L"Get",
40     L"HasValue",     L"If",        L"Ipmt",     L"IsoDate2Num",
41     L"IsoTime2Num",  L"Left",      L"Len",      L"LocalDateFmt",
42     L"LocalTimeFmt", L"Lower",     L"Ltrim",    L"Max",
43     L"Min",          L"Mod",       L"NPV",      L"Num2Date",
44     L"Num2GMTime",   L"Num2Time",  L"Oneof",    L"Parse",
45     L"Pmt",          L"Post",      L"PPmt",     L"Put",
46     L"PV",           L"Rate",      L"Ref",      L"Replace",
47     L"Right",        L"Round",     L"Rtrim",    L"Space",
48     L"Str",          L"Stuff",     L"Substr",   L"Sum",
49     L"Term",         L"Time",      L"Time2Num", L"TimeFmt",
50     L"UnitType",     L"UnitValue", L"Upper",    L"Uuid",
51     L"Within",       L"WordNum",
52 };
53 
54 const size_t g_BuiltInFuncsMaxLen = 12;
55 
56 struct XFA_FMSOMMethod {
57   const wchar_t* m_wsSomMethodName;
58   uint32_t m_dParameters;
59 };
60 
61 const XFA_FMSOMMethod gs_FMSomMethods[] = {
62     {L"absPage", 0x01},
63     {L"absPageInBatch", 0x01},
64     {L"absPageSpan", 0x01},
65     {L"append", 0x01},
66     {L"clear", 0x01},
67     {L"formNodes", 0x01},
68     {L"h", 0x01},
69     {L"insert", 0x03},
70     {L"isRecordGroup", 0x01},
71     {L"page", 0x01},
72     {L"pageSpan", 0x01},
73     {L"remove", 0x01},
74     {L"saveFilteredXML", 0x01},
75     {L"setElement", 0x01},
76     {L"sheet", 0x01},
77     {L"sheetInBatch", 0x01},
78     {L"sign", 0x61},
79     {L"verify", 0x0d},
80     {L"w", 0x01},
81     {L"x", 0x01},
82     {L"y", 0x01},
83 };
84 
85 }  // namespace
86 
XFA_FM_EXPTypeToString(XFA_FM_SimpleExpressionType simpleExpType)87 WideStringView XFA_FM_EXPTypeToString(
88     XFA_FM_SimpleExpressionType simpleExpType) {
89   return gs_lpStrExpFuncName[simpleExpType];
90 }
91 
CXFA_FMSimpleExpression(uint32_t line,XFA_FM_TOKEN op)92 CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op)
93     : m_line(line), m_op(op) {}
94 
ToJavaScript(CFX_WideTextBuf & javascript)95 bool CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
96   CXFA_FMToJavaScriptDepth depthManager;
97   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
98 }
99 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)100 bool CXFA_FMSimpleExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
101   CXFA_FMToJavaScriptDepth depthManager;
102   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
103 }
104 
GetOperatorToken() const105 XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const {
106   return m_op;
107 }
108 
CXFA_FMNullExpression(uint32_t line)109 CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line)
110     : CXFA_FMSimpleExpression(line, TOKnull) {}
111 
ToJavaScript(CFX_WideTextBuf & javascript)112 bool CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
113   CXFA_FMToJavaScriptDepth depthManager;
114   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
115     return false;
116 
117   javascript << L"null";
118   return !CXFA_IsTooBig(javascript);
119 }
120 
CXFA_FMNumberExpression(uint32_t line,WideStringView wsNumber)121 CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line,
122                                                  WideStringView wsNumber)
123     : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {}
124 
~CXFA_FMNumberExpression()125 CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {}
126 
ToJavaScript(CFX_WideTextBuf & javascript)127 bool CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
128   CXFA_FMToJavaScriptDepth depthManager;
129   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
130     return false;
131 
132   javascript << m_wsNumber;
133   return !CXFA_IsTooBig(javascript);
134 }
135 
CXFA_FMStringExpression(uint32_t line,WideStringView wsString)136 CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line,
137                                                  WideStringView wsString)
138     : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {}
139 
~CXFA_FMStringExpression()140 CXFA_FMStringExpression::~CXFA_FMStringExpression() {}
141 
ToJavaScript(CFX_WideTextBuf & javascript)142 bool CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
143   CXFA_FMToJavaScriptDepth depthManager;
144   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
145     return false;
146 
147   WideString tempStr(m_wsString);
148   if (tempStr.GetLength() <= 2) {
149     javascript << tempStr;
150     return !CXFA_IsTooBig(javascript);
151   }
152   javascript.AppendChar(L'\"');
153   for (size_t i = 1; i < tempStr.GetLength() - 1; i++) {
154     wchar_t oneChar = tempStr[i];
155     switch (oneChar) {
156       case L'\"':
157         i++;
158         javascript << L"\\\"";
159         break;
160       case 0x0d:
161         break;
162       case 0x0a:
163         javascript << L"\\n";
164         break;
165       default:
166         javascript.AppendChar(oneChar);
167         break;
168     }
169   }
170   javascript.AppendChar(L'\"');
171   return !CXFA_IsTooBig(javascript);
172 }
173 
CXFA_FMIdentifierExpression(uint32_t line,WideStringView wsIdentifier)174 CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression(
175     uint32_t line,
176     WideStringView wsIdentifier)
177     : CXFA_FMSimpleExpression(line, TOKidentifier),
178       m_wsIdentifier(wsIdentifier) {}
179 
~CXFA_FMIdentifierExpression()180 CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {}
181 
ToJavaScript(CFX_WideTextBuf & javascript)182 bool CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
183   CXFA_FMToJavaScriptDepth depthManager;
184   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
185     return false;
186 
187   WideString tempStr(m_wsIdentifier);
188   if (tempStr == L"$") {
189     tempStr = L"this";
190   } else if (tempStr == L"!") {
191     tempStr = L"xfa.datasets";
192   } else if (tempStr == L"$data") {
193     tempStr = L"xfa.datasets.data";
194   } else if (tempStr == L"$event") {
195     tempStr = L"xfa.event";
196   } else if (tempStr == L"$form") {
197     tempStr = L"xfa.form";
198   } else if (tempStr == L"$host") {
199     tempStr = L"xfa.host";
200   } else if (tempStr == L"$layout") {
201     tempStr = L"xfa.layout";
202   } else if (tempStr == L"$template") {
203     tempStr = L"xfa.template";
204   } else if (tempStr[0] == L'!') {
205     tempStr =
206         EXCLAMATION_IN_IDENTIFIER + tempStr.Right(tempStr.GetLength() - 1);
207   }
208   javascript << tempStr;
209   return !CXFA_IsTooBig(javascript);
210 }
211 
CXFA_FMUnaryExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp)212 CXFA_FMUnaryExpression::CXFA_FMUnaryExpression(
213     uint32_t line,
214     XFA_FM_TOKEN op,
215     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
216     : CXFA_FMSimpleExpression(line, op), m_pExp(std::move(pExp)) {}
217 
~CXFA_FMUnaryExpression()218 CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {}
219 
ToJavaScript(CFX_WideTextBuf & javascript)220 bool CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
221   CXFA_FMToJavaScriptDepth depthManager;
222   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
223 }
224 
CXFA_FMBinExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)225 CXFA_FMBinExpression::CXFA_FMBinExpression(
226     uint32_t line,
227     XFA_FM_TOKEN op,
228     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
229     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
230     : CXFA_FMSimpleExpression(line, op),
231       m_pExp1(std::move(pExp1)),
232       m_pExp2(std::move(pExp2)) {}
233 
~CXFA_FMBinExpression()234 CXFA_FMBinExpression::~CXFA_FMBinExpression() {}
235 
ToJavaScript(CFX_WideTextBuf & javascript)236 bool CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
237   CXFA_FMToJavaScriptDepth depthManager;
238   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
239 }
240 
CXFA_FMAssignExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)241 CXFA_FMAssignExpression::CXFA_FMAssignExpression(
242     uint32_t line,
243     XFA_FM_TOKEN op,
244     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
245     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
246     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
247 
ToJavaScript(CFX_WideTextBuf & javascript)248 bool CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
249   CXFA_FMToJavaScriptDepth depthManager;
250   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
251     return false;
252 
253   javascript << L"if (";
254   javascript << gs_lpStrExpFuncName[ISFMOBJECT];
255   javascript << L"(";
256   CFX_WideTextBuf tempExp1;
257   if (!m_pExp1->ToJavaScript(tempExp1))
258     return false;
259   javascript << tempExp1;
260   javascript << L"))\n{\n";
261   javascript << gs_lpStrExpFuncName[ASSIGN];
262   javascript << L"(";
263   javascript << tempExp1;
264   javascript << L", ";
265 
266   CFX_WideTextBuf tempExp2;
267   if (!m_pExp2->ToJavaScript(tempExp2))
268     return false;
269   javascript << tempExp2;
270   javascript << L");\n}\n";
271   if (m_pExp1->GetOperatorToken() == TOKidentifier &&
272       tempExp1.AsStringView() != L"this") {
273     javascript << L"else\n{\n";
274     javascript << tempExp1;
275     javascript << L" = ";
276     javascript << gs_lpStrExpFuncName[ASSIGN];
277     javascript << L"(";
278     javascript << tempExp1;
279     javascript << L", ";
280     javascript << tempExp2;
281     javascript << L");\n}\n";
282   }
283   return !CXFA_IsTooBig(javascript);
284 }
285 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)286 bool CXFA_FMAssignExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
287   CXFA_FMToJavaScriptDepth depthManager;
288   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
289     return false;
290 
291   javascript << L"if (";
292   javascript << gs_lpStrExpFuncName[ISFMOBJECT];
293   javascript << L"(";
294   CFX_WideTextBuf tempExp1;
295   if (!m_pExp1->ToJavaScript(tempExp1))
296     return false;
297   javascript << tempExp1;
298   javascript << L"))\n{\n";
299   javascript << RUNTIMEFUNCTIONRETURNVALUE;
300   javascript << L" = ";
301   javascript << gs_lpStrExpFuncName[ASSIGN];
302   javascript << L"(";
303   javascript << tempExp1;
304   javascript << L", ";
305 
306   CFX_WideTextBuf tempExp2;
307   if (!m_pExp2->ToJavaScript(tempExp2))
308     return false;
309   javascript << tempExp2;
310   javascript << L");\n}\n";
311   if (m_pExp1->GetOperatorToken() == TOKidentifier &&
312       tempExp1.AsStringView() != L"this") {
313     javascript << L"else\n{\n";
314     javascript << RUNTIMEFUNCTIONRETURNVALUE;
315     javascript << L" = ";
316     javascript << tempExp1;
317     javascript << L" = ";
318     javascript << gs_lpStrExpFuncName[ASSIGN];
319     javascript << L"(";
320     javascript << tempExp1;
321     javascript << L", ";
322     javascript << tempExp2;
323     javascript << L");\n}\n";
324   }
325   return !CXFA_IsTooBig(javascript);
326 }
327 
CXFA_FMLogicalOrExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)328 CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression(
329     uint32_t line,
330     XFA_FM_TOKEN op,
331     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
332     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
333     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
334 
ToJavaScript(CFX_WideTextBuf & javascript)335 bool CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
336   CXFA_FMToJavaScriptDepth depthManager;
337   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
338     return false;
339 
340   javascript << gs_lpStrExpFuncName[LOGICALOR];
341   javascript << L"(";
342   if (!m_pExp1->ToJavaScript(javascript))
343     return false;
344   javascript << L", ";
345   if (!m_pExp2->ToJavaScript(javascript))
346     return false;
347   javascript << L")";
348   return !CXFA_IsTooBig(javascript);
349 }
350 
CXFA_FMLogicalAndExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)351 CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression(
352     uint32_t line,
353     XFA_FM_TOKEN op,
354     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
355     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
356     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
357 
ToJavaScript(CFX_WideTextBuf & javascript)358 bool CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
359   CXFA_FMToJavaScriptDepth depthManager;
360   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
361     return false;
362 
363   javascript << gs_lpStrExpFuncName[LOGICALAND];
364   javascript << L"(";
365   if (!m_pExp1->ToJavaScript(javascript))
366     return false;
367   javascript << L", ";
368   if (!m_pExp2->ToJavaScript(javascript))
369     return false;
370   javascript << L")";
371   return !CXFA_IsTooBig(javascript);
372 }
373 
CXFA_FMEqualityExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)374 CXFA_FMEqualityExpression::CXFA_FMEqualityExpression(
375     uint32_t line,
376     XFA_FM_TOKEN op,
377     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
378     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
379     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
380 
ToJavaScript(CFX_WideTextBuf & javascript)381 bool CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
382   CXFA_FMToJavaScriptDepth depthManager;
383   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
384     return false;
385 
386   switch (m_op) {
387     case TOKeq:
388     case TOKkseq:
389       javascript << gs_lpStrExpFuncName[EQUALITY];
390       break;
391     case TOKne:
392     case TOKksne:
393       javascript << gs_lpStrExpFuncName[NOTEQUALITY];
394       break;
395     default:
396       NOTREACHED();
397       break;
398   }
399   javascript << L"(";
400   if (!m_pExp1->ToJavaScript(javascript))
401     return false;
402   javascript << L", ";
403   if (!m_pExp2->ToJavaScript(javascript))
404     return false;
405   javascript << L")";
406   return !CXFA_IsTooBig(javascript);
407 }
408 
CXFA_FMRelationalExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)409 CXFA_FMRelationalExpression::CXFA_FMRelationalExpression(
410     uint32_t line,
411     XFA_FM_TOKEN op,
412     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
413     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
414     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
415 
ToJavaScript(CFX_WideTextBuf & javascript)416 bool CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
417   CXFA_FMToJavaScriptDepth depthManager;
418   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
419     return false;
420 
421   switch (m_op) {
422     case TOKlt:
423     case TOKkslt:
424       javascript << gs_lpStrExpFuncName[LESS];
425       break;
426     case TOKgt:
427     case TOKksgt:
428       javascript << gs_lpStrExpFuncName[GREATER];
429       break;
430     case TOKle:
431     case TOKksle:
432       javascript << gs_lpStrExpFuncName[LESSEQUAL];
433       break;
434     case TOKge:
435     case TOKksge:
436       javascript << gs_lpStrExpFuncName[GREATEREQUAL];
437       break;
438     default:
439       NOTREACHED();
440       break;
441   }
442   javascript << L"(";
443   if (!m_pExp1->ToJavaScript(javascript))
444     return false;
445   javascript << L", ";
446   if (!m_pExp2->ToJavaScript(javascript))
447     return false;
448   javascript << L")";
449   return !CXFA_IsTooBig(javascript);
450 }
451 
CXFA_FMAdditiveExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)452 CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression(
453     uint32_t line,
454     XFA_FM_TOKEN op,
455     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
456     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
457     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
458 
ToJavaScript(CFX_WideTextBuf & javascript)459 bool CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
460   CXFA_FMToJavaScriptDepth depthManager;
461   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
462     return false;
463 
464   switch (m_op) {
465     case TOKplus:
466       javascript << gs_lpStrExpFuncName[PLUS];
467       break;
468     case TOKminus:
469       javascript << gs_lpStrExpFuncName[MINUS];
470       break;
471     default:
472       NOTREACHED();
473       break;
474   }
475   javascript << L"(";
476   if (!m_pExp1->ToJavaScript(javascript))
477     return false;
478   javascript << L", ";
479   if (!m_pExp2->ToJavaScript(javascript))
480     return false;
481   javascript << L")";
482   return !CXFA_IsTooBig(javascript);
483 }
484 
CXFA_FMMultiplicativeExpression(uint32_t line,XFA_FM_TOKEN op,std::unique_ptr<CXFA_FMSimpleExpression> pExp1,std::unique_ptr<CXFA_FMSimpleExpression> pExp2)485 CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression(
486     uint32_t line,
487     XFA_FM_TOKEN op,
488     std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
489     std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
490     : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {}
491 
ToJavaScript(CFX_WideTextBuf & javascript)492 bool CXFA_FMMultiplicativeExpression::ToJavaScript(
493     CFX_WideTextBuf& javascript) {
494   CXFA_FMToJavaScriptDepth depthManager;
495   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
496     return false;
497 
498   switch (m_op) {
499     case TOKmul:
500       javascript << gs_lpStrExpFuncName[MULTIPLE];
501       break;
502     case TOKdiv:
503       javascript << gs_lpStrExpFuncName[DIVIDE];
504       break;
505     default:
506       NOTREACHED();
507       break;
508   }
509   javascript << L"(";
510   if (!m_pExp1->ToJavaScript(javascript))
511     return false;
512   javascript << L", ";
513   if (!m_pExp2->ToJavaScript(javascript))
514     return false;
515   javascript << L")";
516   return !CXFA_IsTooBig(javascript);
517 }
518 
CXFA_FMPosExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp)519 CXFA_FMPosExpression::CXFA_FMPosExpression(
520     uint32_t line,
521     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
522     : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {}
523 
ToJavaScript(CFX_WideTextBuf & javascript)524 bool CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
525   CXFA_FMToJavaScriptDepth depthManager;
526   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
527     return false;
528 
529   javascript << gs_lpStrExpFuncName[POSITIVE];
530   javascript << L"(";
531   if (!m_pExp->ToJavaScript(javascript))
532     return false;
533   javascript << L")";
534   return !CXFA_IsTooBig(javascript);
535 }
536 
CXFA_FMNegExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp)537 CXFA_FMNegExpression::CXFA_FMNegExpression(
538     uint32_t line,
539     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
540     : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {}
541 
ToJavaScript(CFX_WideTextBuf & javascript)542 bool CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
543   CXFA_FMToJavaScriptDepth depthManager;
544   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
545     return false;
546 
547   javascript << gs_lpStrExpFuncName[NEGATIVE];
548   javascript << L"(";
549   if (!m_pExp->ToJavaScript(javascript))
550     return false;
551   javascript << L")";
552   return !CXFA_IsTooBig(javascript);
553 }
554 
CXFA_FMNotExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp)555 CXFA_FMNotExpression::CXFA_FMNotExpression(
556     uint32_t line,
557     std::unique_ptr<CXFA_FMSimpleExpression> pExp)
558     : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {}
559 
ToJavaScript(CFX_WideTextBuf & javascript)560 bool CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
561   CXFA_FMToJavaScriptDepth depthManager;
562   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
563     return false;
564 
565   javascript << gs_lpStrExpFuncName[NOT];
566   javascript << L"(";
567   if (!m_pExp->ToJavaScript(javascript))
568     return false;
569   javascript << L")";
570   return !CXFA_IsTooBig(javascript);
571 }
572 
CXFA_FMCallExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExp,std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> && pArguments,bool bIsSomMethod)573 CXFA_FMCallExpression::CXFA_FMCallExpression(
574     uint32_t line,
575     std::unique_ptr<CXFA_FMSimpleExpression> pExp,
576     std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments,
577     bool bIsSomMethod)
578     : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)),
579       m_bIsSomMethod(bIsSomMethod),
580       m_Arguments(std::move(pArguments)) {}
581 
~CXFA_FMCallExpression()582 CXFA_FMCallExpression::~CXFA_FMCallExpression() {}
583 
IsBuiltInFunc(CFX_WideTextBuf * funcName)584 bool CXFA_FMCallExpression::IsBuiltInFunc(CFX_WideTextBuf* funcName) {
585   if (funcName->GetLength() > g_BuiltInFuncsMaxLen)
586     return false;
587 
588   auto cmpFunc = [](const wchar_t* iter, const WideString& val) -> bool {
589     return val.CompareNoCase(iter) > 0;
590   };
591   WideString str = funcName->MakeString();
592   const wchar_t* const* pMatchResult = std::lower_bound(
593       std::begin(g_BuiltInFuncs), std::end(g_BuiltInFuncs), str, cmpFunc);
594   if (pMatchResult != std::end(g_BuiltInFuncs) &&
595       !str.CompareNoCase(*pMatchResult)) {
596     funcName->Clear();
597     *funcName << *pMatchResult;
598     return true;
599   }
600   return false;
601 }
602 
IsMethodWithObjParam(const WideString & methodName)603 uint32_t CXFA_FMCallExpression::IsMethodWithObjParam(
604     const WideString& methodName) {
605   auto cmpFunc = [](const XFA_FMSOMMethod iter, const WideString& val) {
606     return val.Compare(iter.m_wsSomMethodName) > 0;
607   };
608   const XFA_FMSOMMethod* result =
609       std::lower_bound(std::begin(gs_FMSomMethods), std::end(gs_FMSomMethods),
610                        methodName, cmpFunc);
611   if (result != std::end(gs_FMSomMethods) &&
612       !methodName.Compare(result->m_wsSomMethodName)) {
613     return result->m_dParameters;
614   }
615   return 0;
616 }
617 
ToJavaScript(CFX_WideTextBuf & javascript)618 bool CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
619   CXFA_FMToJavaScriptDepth depthManager;
620   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
621     return false;
622 
623   CFX_WideTextBuf funcName;
624   if (!m_pExp->ToJavaScript(funcName))
625     return false;
626   if (m_bIsSomMethod) {
627     javascript << funcName;
628     javascript << L"(";
629     uint32_t methodPara = IsMethodWithObjParam(funcName.MakeString());
630     if (methodPara > 0) {
631       for (size_t i = 0; i < m_Arguments.size(); ++i) {
632         // Currently none of our expressions use objects for a parameter over
633         // the 6th. Make sure we don't overflow the shift when doing this
634         // check. If we ever need more the 32 object params we can revisit.
635         if (i < 32 && (methodPara & (0x01 << i)) > 0) {
636           javascript << gs_lpStrExpFuncName[GETFMJSOBJ];
637         } else {
638           javascript << gs_lpStrExpFuncName[GETFMVALUE];
639         }
640         javascript << L"(";
641         const auto& expr = m_Arguments[i];
642         if (!expr->ToJavaScript(javascript))
643           return false;
644         javascript << L")";
645         if (i + 1 < m_Arguments.size()) {
646           javascript << L", ";
647         }
648       }
649     } else {
650       for (const auto& expr : m_Arguments) {
651         javascript << gs_lpStrExpFuncName[GETFMVALUE];
652         javascript << L"(";
653         if (!expr->ToJavaScript(javascript))
654           return false;
655         javascript << L")";
656         if (expr != m_Arguments.back())
657           javascript << L", ";
658       }
659     }
660     javascript << L")";
661   } else {
662     bool isEvalFunc = false;
663     bool isExistsFunc = false;
664     if (IsBuiltInFunc(&funcName)) {
665       if (funcName.AsStringView() == L"Eval") {
666         isEvalFunc = true;
667         javascript << L"eval.call(this, ";
668         javascript << gs_lpStrExpFuncName[CALL];
669         javascript << L"Translate";
670       } else if (funcName.AsStringView() == L"Exists") {
671         isExistsFunc = true;
672         javascript << gs_lpStrExpFuncName[CALL];
673         javascript << funcName;
674       } else {
675         javascript << gs_lpStrExpFuncName[CALL];
676         javascript << funcName;
677       }
678     } else {
679       // If a function is not a SomMethod or a built-in then the input was
680       // invalid, so failing. The scanner/lexer should catch this, but currently
681       // doesn't. This failure will bubble up to the top-level and cause the
682       // transpile to fail.
683       return false;
684     }
685     javascript << L"(";
686     if (isExistsFunc) {
687       javascript << L"\n(\nfunction ()\n{\ntry\n{\n";
688       if (!m_Arguments.empty()) {
689         const auto& expr = m_Arguments[0];
690         javascript << L"return ";
691         if (!expr->ToJavaScript(javascript))
692           return false;
693         javascript << L";\n}\n";
694       } else {
695         javascript << L"return 0;\n}\n";
696       }
697       javascript << L"catch(accessExceptions)\n";
698       javascript << L"{\nreturn 0;\n}\n}\n).call(this)\n";
699     } else {
700       for (const auto& expr : m_Arguments) {
701         if (!expr->ToJavaScript(javascript))
702           return false;
703         if (expr != m_Arguments.back())
704           javascript << L", ";
705       }
706     }
707     javascript << L")";
708     if (isEvalFunc) {
709       javascript << L")";
710     }
711   }
712   return !CXFA_IsTooBig(javascript);
713 }
714 
CXFA_FMDotAccessorExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,XFA_FM_TOKEN op,WideStringView wsIdentifier,std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)715 CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression(
716     uint32_t line,
717     std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
718     XFA_FM_TOKEN op,
719     WideStringView wsIdentifier,
720     std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
721     : CXFA_FMBinExpression(line,
722                            op,
723                            std::move(pAccessor),
724                            std::move(pIndexExp)),
725       m_wsIdentifier(wsIdentifier) {}
726 
~CXFA_FMDotAccessorExpression()727 CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {}
728 
ToJavaScript(CFX_WideTextBuf & javascript)729 bool CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
730   CXFA_FMToJavaScriptDepth depthManager;
731   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
732     return false;
733 
734   javascript << gs_lpStrExpFuncName[DOT];
735   javascript << L"(";
736   CFX_WideTextBuf tempExp1;
737   if (m_pExp1) {
738     if (!m_pExp1->ToJavaScript(tempExp1))
739       return false;
740     javascript << tempExp1;
741   } else {
742     javascript << L"null";
743   }
744   javascript << L", ";
745   javascript << L"\"";
746 
747   if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier)
748     javascript << tempExp1;
749   javascript << L"\", ";
750   if (m_op == TOKdotscream) {
751     javascript << L"\"#";
752     javascript << m_wsIdentifier;
753     javascript << L"\", ";
754   } else if (m_op == TOKdotstar) {
755     javascript << L"\"*\", ";
756   } else if (m_op == TOKcall) {
757     javascript << L"\"\", ";
758   } else {
759     javascript << L"\"";
760     javascript << m_wsIdentifier;
761     javascript << L"\", ";
762   }
763   if (!m_pExp2->ToJavaScript(javascript))
764     return false;
765   javascript << L")";
766   return !CXFA_IsTooBig(javascript);
767 }
768 
CXFA_FMIndexExpression(uint32_t line,XFA_FM_AccessorIndex accessorIndex,std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp,bool bIsStarIndex)769 CXFA_FMIndexExpression::CXFA_FMIndexExpression(
770     uint32_t line,
771     XFA_FM_AccessorIndex accessorIndex,
772     std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp,
773     bool bIsStarIndex)
774     : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)),
775       m_accessorIndex(accessorIndex),
776       m_bIsStarIndex(bIsStarIndex) {}
777 
ToJavaScript(CFX_WideTextBuf & javascript)778 bool CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
779   CXFA_FMToJavaScriptDepth depthManager;
780   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
781     return false;
782 
783   switch (m_accessorIndex) {
784     case ACCESSOR_NO_INDEX:
785       javascript << L"0";
786       break;
787     case ACCESSOR_NO_RELATIVEINDEX:
788       javascript << L"1";
789       break;
790     case ACCESSOR_POSITIVE_INDEX:
791       javascript << L"2";
792       break;
793     case ACCESSOR_NEGATIVE_INDEX:
794       javascript << L"3";
795       break;
796     default:
797       javascript << L"0";
798   }
799   if (!m_bIsStarIndex) {
800     javascript << L", ";
801     if (m_pExp) {
802       if (!m_pExp->ToJavaScript(javascript))
803         return false;
804     } else {
805       javascript << L"0";
806     }
807   }
808   return !CXFA_IsTooBig(javascript);
809 }
810 
CXFA_FMDotDotAccessorExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,XFA_FM_TOKEN op,WideStringView wsIdentifier,std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)811 CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression(
812     uint32_t line,
813     std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
814     XFA_FM_TOKEN op,
815     WideStringView wsIdentifier,
816     std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
817     : CXFA_FMBinExpression(line,
818                            op,
819                            std::move(pAccessor),
820                            std::move(pIndexExp)),
821       m_wsIdentifier(wsIdentifier) {}
822 
~CXFA_FMDotDotAccessorExpression()823 CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {}
824 
ToJavaScript(CFX_WideTextBuf & javascript)825 bool CXFA_FMDotDotAccessorExpression::ToJavaScript(
826     CFX_WideTextBuf& javascript) {
827   CXFA_FMToJavaScriptDepth depthManager;
828   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
829     return false;
830 
831   javascript << gs_lpStrExpFuncName[DOTDOT];
832   javascript << L"(";
833   CFX_WideTextBuf tempExp1;
834   if (!m_pExp1->ToJavaScript(tempExp1))
835     return false;
836   javascript << tempExp1;
837   javascript << L", ";
838   javascript << L"\"";
839 
840   if (m_pExp1->GetOperatorToken() == TOKidentifier)
841     javascript << tempExp1;
842   javascript << L"\", ";
843   javascript << L"\"";
844   javascript << m_wsIdentifier;
845   javascript << L"\", ";
846   if (!m_pExp2->ToJavaScript(javascript))
847     return false;
848   javascript << L")";
849   return !CXFA_IsTooBig(javascript);
850 }
851 
CXFA_FMMethodCallExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1,std::unique_ptr<CXFA_FMSimpleExpression> pCallExp)852 CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression(
853     uint32_t line,
854     std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1,
855     std::unique_ptr<CXFA_FMSimpleExpression> pCallExp)
856     : CXFA_FMBinExpression(line,
857                            TOKdot,
858                            std::move(pAccessorExp1),
859                            std::move(pCallExp)) {}
860 
ToJavaScript(CFX_WideTextBuf & javascript)861 bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
862   CXFA_FMToJavaScriptDepth depthManager;
863   if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
864     return false;
865 
866   javascript << L"(\nfunction ()\n{\n";
867   javascript << L"var method_return_value = null;\n";
868   javascript << L"var accessor_object = ";
869   if (!m_pExp1->ToJavaScript(javascript))
870     return false;
871   javascript << L";\n";
872   javascript << L"if (";
873   javascript << gs_lpStrExpFuncName[ISFMARRAY];
874   javascript << L"(accessor_object))\n{\n";
875   javascript << L"for(var index = accessor_object.length - 1; index > 1; "
876                 L"index--)\n{\n";
877   javascript << L"method_return_value = accessor_object[index].";
878 
879   CFX_WideTextBuf tempExp2;
880   if (!m_pExp2->ToJavaScript(tempExp2))
881     return false;
882   javascript << tempExp2;
883   javascript << L";\n}\n}\n";
884   javascript << L"else\n{\nmethod_return_value = accessor_object.";
885   javascript << tempExp2;
886   javascript << L";\n}\n";
887   javascript << L"return method_return_value;\n";
888   javascript << L"}\n).call(this)";
889   return !CXFA_IsTooBig(javascript);
890 }
891 
CXFA_IsTooBig(const CFX_WideTextBuf & javascript)892 bool CXFA_IsTooBig(const CFX_WideTextBuf& javascript) {
893   return javascript.GetSize() >= 256 * 1024 * 1024;
894 }
895