// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h" #include #include #include #include "core/fxcrt/autorestorer.h" #include "core/fxcrt/cfx_widetextbuf.h" #include "core/fxcrt/fx_extension.h" #include "third_party/base/logging.h" #include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h" namespace { // Indexed by XFA_FM_SimpleExpressionType const wchar_t* const gs_lpStrExpFuncName[] = { L"pfm_rt.asgn_val_op", L"pfm_rt.log_or_op", L"pfm_rt.log_and_op", L"pfm_rt.eq_op", L"pfm_rt.neq_op", L"pfm_rt.lt_op", L"pfm_rt.le_op", L"pfm_rt.gt_op", L"pfm_rt.ge_op", L"pfm_rt.plus_op", L"pfm_rt.minus_op", L"pfm_rt.mul_op", L"pfm_rt.div_op", L"pfm_rt.pos_op", L"pfm_rt.neg_op", L"pfm_rt.log_not_op", L"pfm_rt.", L"pfm_rt.dot_acc", L"pfm_rt.dotdot_acc", L"pfm_rt.concat_obj", L"pfm_rt.is_obj", L"pfm_rt.is_ary", L"pfm_rt.get_val", L"pfm_rt.get_jsobj", L"pfm_rt.var_filter", }; const wchar_t* const g_BuiltInFuncs[] = { L"Abs", L"Apr", L"At", L"Avg", L"Ceil", L"Choose", L"Concat", L"Count", L"Cterm", L"Date", L"Date2Num", L"DateFmt", L"Decode", L"Encode", L"Eval", L"Exists", L"Floor", L"Format", L"FV", L"Get", L"HasValue", L"If", L"Ipmt", L"IsoDate2Num", L"IsoTime2Num", L"Left", L"Len", L"LocalDateFmt", L"LocalTimeFmt", L"Lower", L"Ltrim", L"Max", L"Min", L"Mod", L"NPV", L"Num2Date", L"Num2GMTime", L"Num2Time", L"Oneof", L"Parse", L"Pmt", L"Post", L"PPmt", L"Put", L"PV", L"Rate", L"Ref", L"Replace", L"Right", L"Round", L"Rtrim", L"Space", L"Str", L"Stuff", L"Substr", L"Sum", L"Term", L"Time", L"Time2Num", L"TimeFmt", L"UnitType", L"UnitValue", L"Upper", L"Uuid", L"Within", L"WordNum", }; const size_t g_BuiltInFuncsMaxLen = 12; struct XFA_FMSOMMethod { const wchar_t* m_wsSomMethodName; uint32_t m_dParameters; }; const XFA_FMSOMMethod gs_FMSomMethods[] = { {L"absPage", 0x01}, {L"absPageInBatch", 0x01}, {L"absPageSpan", 0x01}, {L"append", 0x01}, {L"clear", 0x01}, {L"formNodes", 0x01}, {L"h", 0x01}, {L"insert", 0x03}, {L"isRecordGroup", 0x01}, {L"page", 0x01}, {L"pageSpan", 0x01}, {L"remove", 0x01}, {L"saveFilteredXML", 0x01}, {L"setElement", 0x01}, {L"sheet", 0x01}, {L"sheetInBatch", 0x01}, {L"sign", 0x61}, {L"verify", 0x0d}, {L"w", 0x01}, {L"x", 0x01}, {L"y", 0x01}, }; } // namespace WideStringView XFA_FM_EXPTypeToString( XFA_FM_SimpleExpressionType simpleExpType) { return gs_lpStrExpFuncName[simpleExpType]; } CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op) : m_line(line), m_op(op) {} bool CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); } XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const { return m_op; } CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line) : CXFA_FMSimpleExpression(line, TOKnull) {} bool CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << L"null"; return !CXFA_IsTooBig(javascript); } CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line, WideStringView wsNumber) : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {} CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {} bool CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << m_wsNumber; return !CXFA_IsTooBig(javascript); } CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line, WideStringView wsString) : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {} CXFA_FMStringExpression::~CXFA_FMStringExpression() {} bool CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; WideString tempStr(m_wsString); if (tempStr.GetLength() <= 2) { javascript << tempStr; return !CXFA_IsTooBig(javascript); } javascript.AppendChar(L'\"'); for (size_t i = 1; i < tempStr.GetLength() - 1; i++) { wchar_t oneChar = tempStr[i]; switch (oneChar) { case L'\"': i++; javascript << L"\\\""; break; case 0x0d: break; case 0x0a: javascript << L"\\n"; break; default: javascript.AppendChar(oneChar); break; } } javascript.AppendChar(L'\"'); return !CXFA_IsTooBig(javascript); } CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression( uint32_t line, WideStringView wsIdentifier) : CXFA_FMSimpleExpression(line, TOKidentifier), m_wsIdentifier(wsIdentifier) {} CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {} bool CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; WideString tempStr(m_wsIdentifier); if (tempStr == L"$") { tempStr = L"this"; } else if (tempStr == L"!") { tempStr = L"xfa.datasets"; } else if (tempStr == L"$data") { tempStr = L"xfa.datasets.data"; } else if (tempStr == L"$event") { tempStr = L"xfa.event"; } else if (tempStr == L"$form") { tempStr = L"xfa.form"; } else if (tempStr == L"$host") { tempStr = L"xfa.host"; } else if (tempStr == L"$layout") { tempStr = L"xfa.layout"; } else if (tempStr == L"$template") { tempStr = L"xfa.template"; } else if (tempStr[0] == L'!') { tempStr = L"pfm__excl__" + tempStr.Right(tempStr.GetLength() - 1); } javascript << tempStr; return !CXFA_IsTooBig(javascript); } CXFA_FMUnaryExpression::CXFA_FMUnaryExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp) : CXFA_FMSimpleExpression(line, op), m_pExp(std::move(pExp)) {} CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {} bool CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); } CXFA_FMBinExpression::CXFA_FMBinExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMSimpleExpression(line, op), m_pExp1(std::move(pExp1)), m_pExp2(std::move(pExp2)) {} CXFA_FMBinExpression::~CXFA_FMBinExpression() {} bool CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth(); } CXFA_FMAssignExpression::CXFA_FMAssignExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} bool CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << L"if ("; javascript << gs_lpStrExpFuncName[ISFMOBJECT]; javascript << L"("; CFX_WideTextBuf tempExp1; if (!m_pExp1->ToJavaScript(tempExp1, ReturnType::kInfered)) return false; javascript << tempExp1; javascript << L"))\n{\n"; if (type == ReturnType::kImplied) javascript << L"pfm_ret = "; javascript << gs_lpStrExpFuncName[ASSIGN]; javascript << L"("; javascript << tempExp1; javascript << L", "; CFX_WideTextBuf tempExp2; if (!m_pExp2->ToJavaScript(tempExp2, ReturnType::kInfered)) return false; javascript << tempExp2; javascript << L");\n}\n"; if (m_pExp1->GetOperatorToken() == TOKidentifier && tempExp1.AsStringView() != L"this") { javascript << L"else\n{\n"; if (type == ReturnType::kImplied) javascript << L"pfm_ret = "; javascript << tempExp1; javascript << L" = "; javascript << gs_lpStrExpFuncName[ASSIGN]; javascript << L"("; javascript << tempExp1; javascript << L", "; javascript << tempExp2; javascript << L");\n}\n"; } return !CXFA_IsTooBig(javascript); } CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} bool CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << gs_lpStrExpFuncName[LOGICALOR]; javascript << L"("; if (!m_pExp1->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L", "; if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} bool CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << gs_lpStrExpFuncName[LOGICALAND]; javascript << L"("; if (!m_pExp1->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L", "; if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMEqualityExpression::CXFA_FMEqualityExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} bool CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; switch (m_op) { case TOKeq: case TOKkseq: javascript << gs_lpStrExpFuncName[EQUALITY]; break; case TOKne: case TOKksne: javascript << gs_lpStrExpFuncName[NOTEQUALITY]; break; default: NOTREACHED(); break; } javascript << L"("; if (!m_pExp1->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L", "; if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMRelationalExpression::CXFA_FMRelationalExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} bool CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; switch (m_op) { case TOKlt: case TOKkslt: javascript << gs_lpStrExpFuncName[LESS]; break; case TOKgt: case TOKksgt: javascript << gs_lpStrExpFuncName[GREATER]; break; case TOKle: case TOKksle: javascript << gs_lpStrExpFuncName[LESSEQUAL]; break; case TOKge: case TOKksge: javascript << gs_lpStrExpFuncName[GREATEREQUAL]; break; default: NOTREACHED(); break; } javascript << L"("; if (!m_pExp1->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L", "; if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} bool CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; switch (m_op) { case TOKplus: javascript << gs_lpStrExpFuncName[PLUS]; break; case TOKminus: javascript << gs_lpStrExpFuncName[MINUS]; break; default: NOTREACHED(); break; } javascript << L"("; if (!m_pExp1->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L", "; if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression( uint32_t line, XFA_FM_TOKEN op, std::unique_ptr pExp1, std::unique_ptr pExp2) : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} bool CXFA_FMMultiplicativeExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; switch (m_op) { case TOKmul: javascript << gs_lpStrExpFuncName[MULTIPLE]; break; case TOKdiv: javascript << gs_lpStrExpFuncName[DIVIDE]; break; default: NOTREACHED(); break; } javascript << L"("; if (!m_pExp1->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L", "; if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMPosExpression::CXFA_FMPosExpression( uint32_t line, std::unique_ptr pExp) : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {} bool CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << gs_lpStrExpFuncName[POSITIVE]; javascript << L"("; if (!m_pExp->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMNegExpression::CXFA_FMNegExpression( uint32_t line, std::unique_ptr pExp) : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {} bool CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << gs_lpStrExpFuncName[NEGATIVE]; javascript << L"("; if (!m_pExp->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMNotExpression::CXFA_FMNotExpression( uint32_t line, std::unique_ptr pExp) : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {} bool CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << gs_lpStrExpFuncName[NOT]; javascript << L"("; if (!m_pExp->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMCallExpression::CXFA_FMCallExpression( uint32_t line, std::unique_ptr pExp, std::vector>&& pArguments, bool bIsSomMethod) : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)), m_bIsSomMethod(bIsSomMethod), m_Arguments(std::move(pArguments)) {} CXFA_FMCallExpression::~CXFA_FMCallExpression() {} bool CXFA_FMCallExpression::IsBuiltInFunc(CFX_WideTextBuf* funcName) { if (funcName->GetLength() > g_BuiltInFuncsMaxLen) return false; auto cmpFunc = [](const wchar_t* iter, const WideString& val) -> bool { return val.CompareNoCase(iter) > 0; }; WideString str = funcName->MakeString(); const wchar_t* const* pMatchResult = std::lower_bound( std::begin(g_BuiltInFuncs), std::end(g_BuiltInFuncs), str, cmpFunc); if (pMatchResult != std::end(g_BuiltInFuncs) && !str.CompareNoCase(*pMatchResult)) { funcName->Clear(); *funcName << *pMatchResult; return true; } return false; } uint32_t CXFA_FMCallExpression::IsMethodWithObjParam( const WideString& methodName) { auto cmpFunc = [](const XFA_FMSOMMethod iter, const WideString& val) { return val.Compare(iter.m_wsSomMethodName) > 0; }; const XFA_FMSOMMethod* result = std::lower_bound(std::begin(gs_FMSomMethods), std::end(gs_FMSomMethods), methodName, cmpFunc); if (result != std::end(gs_FMSomMethods) && !methodName.Compare(result->m_wsSomMethodName)) { return result->m_dParameters; } return 0; } bool CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; CFX_WideTextBuf funcName; if (!m_pExp->ToJavaScript(funcName, ReturnType::kInfered)) return false; if (m_bIsSomMethod) { javascript << funcName; javascript << L"("; uint32_t methodPara = IsMethodWithObjParam(funcName.MakeString()); if (methodPara > 0) { for (size_t i = 0; i < m_Arguments.size(); ++i) { // Currently none of our expressions use objects for a parameter over // the 6th. Make sure we don't overflow the shift when doing this // check. If we ever need more the 32 object params we can revisit. if (i < 32 && (methodPara & (0x01 << i)) > 0) { javascript << gs_lpStrExpFuncName[GETFMJSOBJ]; } else { javascript << gs_lpStrExpFuncName[GETFMVALUE]; } javascript << L"("; const auto& expr = m_Arguments[i]; if (!expr->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; if (i + 1 < m_Arguments.size()) { javascript << L", "; } } } else { for (const auto& expr : m_Arguments) { javascript << gs_lpStrExpFuncName[GETFMVALUE]; javascript << L"("; if (!expr->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; if (expr != m_Arguments.back()) javascript << L", "; } } javascript << L")"; } else { bool isEvalFunc = false; bool isExistsFunc = false; if (IsBuiltInFunc(&funcName)) { if (funcName.AsStringView() == L"Eval") { isEvalFunc = true; javascript << L"eval.call(this, "; javascript << gs_lpStrExpFuncName[CALL]; javascript << L"Translate"; } else if (funcName.AsStringView() == L"Exists") { isExistsFunc = true; javascript << gs_lpStrExpFuncName[CALL]; javascript << funcName; } else { javascript << gs_lpStrExpFuncName[CALL]; javascript << funcName; } } else { // If a function is not a SomMethod or a built-in then the input was // invalid, so failing. The scanner/lexer should catch this, but currently // doesn't. This failure will bubble up to the top-level and cause the // transpile to fail. return false; } javascript << L"("; if (isExistsFunc) { javascript << L"\n(\nfunction ()\n{\ntry\n{\n"; if (!m_Arguments.empty()) { const auto& expr = m_Arguments[0]; javascript << L"return "; if (!expr->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L";\n}\n"; } else { javascript << L"return 0;\n}\n"; } javascript << L"catch(accessExceptions)\n"; javascript << L"{\nreturn 0;\n}\n}\n).call(this)\n"; } else { for (const auto& expr : m_Arguments) { if (!expr->ToJavaScript(javascript, ReturnType::kInfered)) return false; if (expr != m_Arguments.back()) javascript << L", "; } } javascript << L")"; if (isEvalFunc) { javascript << L")"; } } return !CXFA_IsTooBig(javascript); } CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression( uint32_t line, std::unique_ptr pAccessor, XFA_FM_TOKEN op, WideStringView wsIdentifier, std::unique_ptr pIndexExp) : CXFA_FMBinExpression(line, op, std::move(pAccessor), std::move(pIndexExp)), m_wsIdentifier(wsIdentifier) {} CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {} bool CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << gs_lpStrExpFuncName[DOT]; javascript << L"("; CFX_WideTextBuf tempExp1; if (m_pExp1) { if (!m_pExp1->ToJavaScript(tempExp1, ReturnType::kInfered)) return false; javascript << tempExp1; } else { javascript << L"null"; } javascript << L", "; javascript << L"\""; if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) javascript << tempExp1; javascript << L"\", "; if (m_op == TOKdotscream) { javascript << L"\"#"; javascript << m_wsIdentifier; javascript << L"\", "; } else if (m_op == TOKdotstar) { javascript << L"\"*\", "; } else if (m_op == TOKcall) { javascript << L"\"\", "; } else { javascript << L"\""; javascript << m_wsIdentifier; javascript << L"\", "; } if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMIndexExpression::CXFA_FMIndexExpression( uint32_t line, XFA_FM_AccessorIndex accessorIndex, std::unique_ptr pIndexExp, bool bIsStarIndex) : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)), m_accessorIndex(accessorIndex), m_bIsStarIndex(bIsStarIndex) {} bool CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; switch (m_accessorIndex) { case ACCESSOR_NO_INDEX: javascript << L"0"; break; case ACCESSOR_NO_RELATIVEINDEX: javascript << L"1"; break; case ACCESSOR_POSITIVE_INDEX: javascript << L"2"; break; case ACCESSOR_NEGATIVE_INDEX: javascript << L"3"; break; default: javascript << L"0"; } if (!m_bIsStarIndex) { javascript << L", "; if (m_pExp) { if (!m_pExp->ToJavaScript(javascript, ReturnType::kInfered)) return false; } else { javascript << L"0"; } } return !CXFA_IsTooBig(javascript); } CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression( uint32_t line, std::unique_ptr pAccessor, XFA_FM_TOKEN op, WideStringView wsIdentifier, std::unique_ptr pIndexExp) : CXFA_FMBinExpression(line, op, std::move(pAccessor), std::move(pIndexExp)), m_wsIdentifier(wsIdentifier) {} CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {} bool CXFA_FMDotDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << gs_lpStrExpFuncName[DOTDOT]; javascript << L"("; CFX_WideTextBuf tempExp1; if (!m_pExp1->ToJavaScript(tempExp1, ReturnType::kInfered)) return false; javascript << tempExp1; javascript << L", "; javascript << L"\""; if (m_pExp1->GetOperatorToken() == TOKidentifier) javascript << tempExp1; javascript << L"\", "; javascript << L"\""; javascript << m_wsIdentifier; javascript << L"\", "; if (!m_pExp2->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L")"; return !CXFA_IsTooBig(javascript); } CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression( uint32_t line, std::unique_ptr pAccessorExp1, std::unique_ptr pCallExp) : CXFA_FMBinExpression(line, TOKdot, std::move(pAccessorExp1), std::move(pCallExp)) {} bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript, ReturnType type) { CXFA_FMToJavaScriptDepth depthManager; if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth()) return false; javascript << L"(\nfunction ()\n{\n"; javascript << L"var method_return_value = null;\n"; javascript << L"var accessor_object = "; if (!m_pExp1->ToJavaScript(javascript, ReturnType::kInfered)) return false; javascript << L";\n"; javascript << L"if ("; javascript << gs_lpStrExpFuncName[ISFMARRAY]; javascript << L"(accessor_object))\n{\n"; javascript << L"for(var index = accessor_object.length - 1; index > 1; " L"index--)\n{\n"; javascript << L"method_return_value = accessor_object[index]."; CFX_WideTextBuf tempExp2; if (!m_pExp2->ToJavaScript(tempExp2, ReturnType::kInfered)) return false; javascript << tempExp2; javascript << L";\n}\n}\n"; javascript << L"else\n{\nmethod_return_value = accessor_object."; javascript << tempExp2; javascript << L";\n}\n"; javascript << L"return method_return_value;\n"; javascript << L"}\n).call(this)"; return !CXFA_IsTooBig(javascript); } bool CXFA_IsTooBig(const CFX_WideTextBuf& javascript) { return javascript.GetSize() >= 256 * 1024 * 1024; }