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