summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2017-05-17 09:39:04 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-05-17 16:21:44 +0000
commitc559156da52805513e11b1b2a057001b6fa63f90 (patch)
treeb8dc7114f1c630cbd9a17ce0ac5400e9f2fad77f
parent938f211b94abc259c1363e632f6e8c5cb5ec5b1b (diff)
downloadpdfium-c559156da52805513e11b1b2a057001b6fa63f90.tar.xz
Adding CXFA_Parse unittests
This CL adds the beginning of unittests for the CXFA_Parse code. Change-Id: I06e556f1a35405bc683c536d390071917ee330a6 Reviewed-on: https://pdfium-review.googlesource.com/5556 Reviewed-by: Nicolás Peña <npm@chromium.org> Commit-Queue: dsinclair <dsinclair@chromium.org>
-rw-r--r--BUILD.gn3
-rw-r--r--testing/libfuzzer/pdf_fm2js_fuzzer.cc10
-rw-r--r--xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp16
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmexpression.h1
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmparse.cpp14
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmparse.h5
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp135
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmprogram.cpp40
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmprogram.h29
9 files changed, 170 insertions, 83 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 7b7e120526..b40acab3ad 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1673,8 +1673,6 @@ if (pdf_enable_xfa) {
"xfa/fxfa/fm2js/cxfa_fmlexer.h",
"xfa/fxfa/fm2js/cxfa_fmparse.cpp",
"xfa/fxfa/fm2js/cxfa_fmparse.h",
- "xfa/fxfa/fm2js/cxfa_fmprogram.cpp",
- "xfa/fxfa/fm2js/cxfa_fmprogram.h",
"xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp",
"xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h",
"xfa/fxfa/fxfa.h",
@@ -1911,6 +1909,7 @@ test("pdfium_unittests") {
"xfa/fxfa/app/xfa_ffbarcode_unittest.cpp",
"xfa/fxfa/cxfa_ffapp_unittest.cpp",
"xfa/fxfa/fm2js/cxfa_fmlexer_unittest.cpp",
+ "xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp",
"xfa/fxfa/fm2js/cxfa_fmsimpleexpression_unittest.cpp",
"xfa/fxfa/parser/xfa_utils_unittest.cpp",
]
diff --git a/testing/libfuzzer/pdf_fm2js_fuzzer.cc b/testing/libfuzzer/pdf_fm2js_fuzzer.cc
index 8cc98fcf54..226fb4096e 100644
--- a/testing/libfuzzer/pdf_fm2js_fuzzer.cc
+++ b/testing/libfuzzer/pdf_fm2js_fuzzer.cc
@@ -8,20 +8,16 @@
#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_string.h"
-#include "xfa/fxfa/fm2js/cxfa_fmprogram.h"
+#include "xfa/fxfa/fm2js/cxfa_fm2jscontext.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FX_SAFE_STRSIZE safe_size = size;
if (!safe_size.IsValid())
return 0;
+ CFX_WideTextBuf js;
CFX_WideString input =
CFX_WideString::FromUTF8(CFX_ByteStringC(data, safe_size.ValueOrDie()));
- CXFA_FMProgram program(input.AsStringC());
- if (!program.ParseProgram())
- return 0;
-
- CFX_WideTextBuf js;
- program.TranslateProgram(js);
+ CXFA_FM2JSContext::Translate(input.AsStringC(), &js);
return 0;
}
diff --git a/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp b/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp
index c9c0f4a379..b074a9aa57 100644
--- a/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp
+++ b/xfa/fxfa/fm2js/cxfa_fm2jscontext.cpp
@@ -18,7 +18,7 @@
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
#include "xfa/fxfa/app/xfa_ffnotify.h"
-#include "xfa/fxfa/fm2js/cxfa_fmprogram.h"
+#include "xfa/fxfa/fm2js/cxfa_fmparse.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_localevalue.h"
#include "xfa/fxfa/parser/cxfa_node.h"
@@ -6119,8 +6119,18 @@ bool CXFA_FM2JSContext::Translate(const CFX_WideStringC& wsFormcalc,
return true;
}
- CXFA_FMProgram program(wsFormcalc);
- return program.ParseProgram() && program.TranslateProgram(*wsJavascript);
+ CXFA_FMErrorInfo errorInfo;
+ CXFA_FMParse parser(wsFormcalc, &errorInfo);
+
+ std::unique_ptr<CXFA_FMFunctionDefinition> func = parser.Parse();
+ if (!errorInfo.message.IsEmpty())
+ return false;
+
+ if (!func->ToJavaScript(*wsJavascript))
+ return false;
+
+ wsJavascript->AppendChar(0);
+ return true;
}
CXFA_FM2JSContext::CXFA_FM2JSContext(v8::Isolate* pScriptIsolate,
diff --git a/xfa/fxfa/fm2js/cxfa_fmexpression.h b/xfa/fxfa/fm2js/cxfa_fmexpression.h
index c04bc2f117..b2bbc43968 100644
--- a/xfa/fxfa/fm2js/cxfa_fmexpression.h
+++ b/xfa/fxfa/fm2js/cxfa_fmexpression.h
@@ -28,6 +28,7 @@ class CXFA_FMExpression {
explicit CXFA_FMExpression(uint32_t line);
CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type);
virtual ~CXFA_FMExpression() {}
+
virtual bool ToJavaScript(CFX_WideTextBuf& javascript);
virtual bool ToImpliedReturnJS(CFX_WideTextBuf&);
uint32_t GetLine() { return m_line; }
diff --git a/xfa/fxfa/fm2js/cxfa_fmparse.cpp b/xfa/fxfa/fm2js/cxfa_fmparse.cpp
index cac7ad1b59..6e80a40d0c 100644
--- a/xfa/fxfa/fm2js/cxfa_fmparse.cpp
+++ b/xfa/fxfa/fm2js/cxfa_fmparse.cpp
@@ -26,6 +26,20 @@ CXFA_FMParse::CXFA_FMParse(const CFX_WideStringC& wsFormcalc,
CXFA_FMParse::~CXFA_FMParse() {}
+std::unique_ptr<CXFA_FMFunctionDefinition> CXFA_FMParse::Parse() {
+ NextToken();
+ if (HasError())
+ return nullptr;
+
+ auto expressions = ParseTopExpression();
+ if (HasError())
+ return nullptr;
+
+ std::vector<CFX_WideStringC> arguments;
+ return pdfium::MakeUnique<CXFA_FMFunctionDefinition>(
+ 1, true, L"", std::move(arguments), std::move(expressions));
+}
+
void CXFA_FMParse::NextToken() {
m_pToken = m_lexer->NextToken();
while (m_pToken->m_type == TOKreserver) {
diff --git a/xfa/fxfa/fm2js/cxfa_fmparse.h b/xfa/fxfa/fm2js/cxfa_fmparse.h
index 43a4450128..625145e7a2 100644
--- a/xfa/fxfa/fm2js/cxfa_fmparse.h
+++ b/xfa/fxfa/fm2js/cxfa_fmparse.h
@@ -18,13 +18,14 @@ class CXFA_FMParse {
CXFA_FMParse(const CFX_WideStringC& wsFormcalc, CXFA_FMErrorInfo* pErrorInfo);
~CXFA_FMParse();
- void NextToken();
- std::vector<std::unique_ptr<CXFA_FMExpression>> ParseTopExpression();
+ std::unique_ptr<CXFA_FMFunctionDefinition> Parse();
private:
+ void NextToken();
void Check(XFA_FM_TOKEN op);
void Error(const wchar_t* msg, ...);
bool HasError() const;
+ std::vector<std::unique_ptr<CXFA_FMExpression>> ParseTopExpression();
std::unique_ptr<CXFA_FMExpression> ParseFunction();
std::unique_ptr<CXFA_FMExpression> ParseExpression();
std::unique_ptr<CXFA_FMExpression> ParseVarExpression();
diff --git a/xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp
new file mode 100644
index 0000000000..a17808ae88
--- /dev/null
+++ b/xfa/fxfa/fm2js/cxfa_fmparse_unittest.cpp
@@ -0,0 +1,135 @@
+// Copyright 2017 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.
+
+#include "xfa/fxfa/fm2js/cxfa_fmparse.h"
+
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+#include "third_party/base/ptr_util.h"
+
+TEST(CXFA_FMParseTest, Empty) {
+ CXFA_FMErrorInfo errorInfo;
+ auto parser = pdfium::MakeUnique<CXFA_FMParse>(L"", &errorInfo);
+ std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse();
+ ASSERT(ast != nullptr);
+ EXPECT_TRUE(errorInfo.message.IsEmpty());
+
+ CFX_WideTextBuf buf;
+ EXPECT_TRUE(ast->ToJavaScript(buf));
+ // TODO(dsinclair): This is a little weird .....
+ EXPECT_EQ(L"// comments only", buf.AsStringC());
+}
+
+TEST(CXFA_FMParseTest, CommentOnlyIsError) {
+ CXFA_FMErrorInfo errorInfo;
+ auto parser = pdfium::MakeUnique<CXFA_FMParse>(L"; Just comment", &errorInfo);
+ std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse();
+ ASSERT(ast != nullptr);
+ // TODO(dsinclair): This isn't allowed per the spec.
+ EXPECT_TRUE(errorInfo.message.IsEmpty());
+ // EXPECT_FALSE(errorInfo.message.IsEmpty());
+
+ CFX_WideTextBuf buf;
+ EXPECT_TRUE(ast->ToJavaScript(buf));
+ EXPECT_EQ(L"// comments only", buf.AsStringC());
+}
+
+TEST(CXFA_FMParseTest, CommentThenValue) {
+ CXFA_FMErrorInfo errorInfo;
+ auto parser =
+ pdfium::MakeUnique<CXFA_FMParse>(L"; Just comment\n12", &errorInfo);
+ std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse();
+ ASSERT(ast != nullptr);
+ EXPECT_TRUE(errorInfo.message.IsEmpty());
+
+ CFX_WideTextBuf buf;
+ EXPECT_TRUE(ast->ToJavaScript(buf));
+ EXPECT_EQ(L"(\n"
+ L"function ()\n"
+ L"{\n"
+ L"var foxit_xfa_formcalc_runtime_func_return_value = null;\n"
+ L"foxit_xfa_formcalc_runtime_func_return_value = 12;\n"
+ L"return foxit_xfa_formcalc_runtime.get_fm_value("
+ L"foxit_xfa_formcalc_runtime_func_return_value);\n"
+ L"}\n"
+ L").call(this);\n", buf.AsStringC());
+}
+
+TEST(CXFA_FMParseTest, Parse) {
+ const wchar_t input[] = L"$ = Avg (-3, 5, -6, 12, -13);\n"
+ L"$ = Avg (Table2..Row[*].Cell1);\n"
+ L"\n"
+ L"if ($ ne -1)then\n"
+ L" border.fill.color.value = \"255,64,64\";\n"
+ L"else\n"
+ L" border.fill.color.value = \"20,170,13\";\n"
+ L"endif\n"
+ L"\n"
+ L"$";
+
+ CXFA_FMErrorInfo errorInfo;
+ auto parser = pdfium::MakeUnique<CXFA_FMParse>(input, &errorInfo);
+ std::unique_ptr<CXFA_FMFunctionDefinition> ast = parser->Parse();
+ ASSERT(ast != nullptr);
+ EXPECT_TRUE(errorInfo.message.IsEmpty());
+
+ CFX_WideTextBuf buf;
+ EXPECT_TRUE(ast->ToJavaScript(buf));
+ EXPECT_EQ(
+ L"(\nfunction ()\n{\n"
+ L"var foxit_xfa_formcalc_runtime_func_return_value = null;\n"
+ L"if (foxit_xfa_formcalc_runtime.is_fm_object(this))\n{\n"
+ L"foxit_xfa_formcalc_runtime.assign_value_operator(this, "
+ L"foxit_xfa_formcalc_runtime.Avg("
+ L"foxit_xfa_formcalc_runtime.negative_operator(3), 5, "
+ L"foxit_xfa_formcalc_runtime.negative_operator(6), 12, "
+ L"foxit_xfa_formcalc_runtime.negative_operator(13)));\n"
+ L"}\n"
+ L"if (foxit_xfa_formcalc_runtime.is_fm_object(this))\n{\n"
+ L"foxit_xfa_formcalc_runtime.assign_value_operator(this, "
+ L"foxit_xfa_formcalc_runtime.Avg("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dotdot_accessor(Table2, \"Table2\", "
+ L"\"Row\", 1), \"\", \"Cell1\", 0, 0)));\n"
+ L"}\n"
+ L"if (foxit_xfa_formcalc_runtime.get_fm_value("
+ L"foxit_xfa_formcalc_runtime.notequality_operator(this, "
+ L"foxit_xfa_formcalc_runtime.negative_operator(1))))\n{\n"
+ L"if (foxit_xfa_formcalc_runtime.is_fm_object("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor(border, "
+ L"\"border\", \"fill\", 0, 0), \"\", \"color\", 0, 0), "
+ L"\"\", \"value\", 0, 0)))\n{\n"
+ L"foxit_xfa_formcalc_runtime.assign_value_operator("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"border, \"border\", \"fill\", 0, 0), \"\", "
+ L"\"color\", 0, 0), \"\", \"value\", 0, 0), "
+ L"\"255,64,64\");\n"
+ L"}\n"
+ L"}\nelse\n{\n"
+ L"if (foxit_xfa_formcalc_runtime.is_fm_object("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"border, \"border\", \"fill\", 0, 0), \"\", \"color\", "
+ L"0, 0), \"\", \"value\", 0, 0)))\n{\n"
+ L"foxit_xfa_formcalc_runtime.assign_value_operator("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"foxit_xfa_formcalc_runtime.dot_accessor("
+ L"border, \"border\", \"fill\", 0, 0), \"\", "
+ L"\"color\", 0, 0), \"\", \"value\", 0, 0), "
+ L"\"20,170,13\");\n"
+ L"}\n"
+ L"}\n"
+ L"foxit_xfa_formcalc_runtime_func_return_value = this;\n"
+ L"return foxit_xfa_formcalc_runtime.get_fm_value("
+ L"foxit_xfa_formcalc_runtime_func_return_value);\n"
+ L"}\n).call(this);\n", buf.AsStringC());
+}
diff --git a/xfa/fxfa/fm2js/cxfa_fmprogram.cpp b/xfa/fxfa/fm2js/cxfa_fmprogram.cpp
deleted file mode 100644
index 6e6385dae0..0000000000
--- a/xfa/fxfa/fm2js/cxfa_fmprogram.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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_fmprogram.h"
-
-#include <utility>
-#include <vector>
-
-#include "third_party/base/ptr_util.h"
-
-CXFA_FMProgram::CXFA_FMProgram(const CFX_WideStringC& wsFormcalc)
- : m_parse(wsFormcalc, &m_pErrorInfo) {}
-
-CXFA_FMProgram::~CXFA_FMProgram() {}
-
-bool CXFA_FMProgram::ParseProgram() {
- m_parse.NextToken();
- if (!m_pErrorInfo.message.IsEmpty())
- return false;
-
- std::vector<std::unique_ptr<CXFA_FMExpression>> expressions =
- m_parse.ParseTopExpression();
- if (!m_pErrorInfo.message.IsEmpty())
- return false;
-
- std::vector<CFX_WideStringC> arguments;
- m_globalFunction = pdfium::MakeUnique<CXFA_FMFunctionDefinition>(
- 1, true, L"", std::move(arguments), std::move(expressions));
- return true;
-}
-
-bool CXFA_FMProgram::TranslateProgram(CFX_WideTextBuf& wsJavaScript) {
- if (!m_globalFunction->ToJavaScript(wsJavaScript))
- return false;
- wsJavaScript.AppendChar(0);
- return true;
-}
diff --git a/xfa/fxfa/fm2js/cxfa_fmprogram.h b/xfa/fxfa/fm2js/cxfa_fmprogram.h
deleted file mode 100644
index e2a8a984f2..0000000000
--- a/xfa/fxfa/fm2js/cxfa_fmprogram.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_FM2JS_CXFA_FMPROGRAM_H_
-#define XFA_FXFA_FM2JS_CXFA_FMPROGRAM_H_
-
-#include <memory>
-
-#include "xfa/fxfa/fm2js/cxfa_fmerrorinfo.h"
-#include "xfa/fxfa/fm2js/cxfa_fmparse.h"
-
-class CXFA_FMProgram {
- public:
- explicit CXFA_FMProgram(const CFX_WideStringC& wsFormcalc);
- ~CXFA_FMProgram();
-
- bool ParseProgram();
- bool TranslateProgram(CFX_WideTextBuf& wsJavaScript);
-
- private:
- CXFA_FMErrorInfo m_pErrorInfo;
- CXFA_FMParse m_parse;
- std::unique_ptr<CXFA_FMFunctionDefinition> m_globalFunction;
-};
-
-#endif // XFA_FXFA_FM2JS_CXFA_FMPROGRAM_H_