Avoid a CHECK failure inside CXFA_AttachNodeList::Insert().
Make sure the node to insert before, when it exists, is actually a
member of the CXFA_AttachNodeList. Give CXFA_List::Insert() a return
value, so when the validation fails, the caller can indicate failure.
BUG=pdfium:1263
Change-Id: Ia11f94a2407281694080d42cddbcc1c076bde5c9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52177
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/BUILD.gn b/fxjs/BUILD.gn
index ae3befc..30648f9 100644
--- a/fxjs/BUILD.gn
+++ b/fxjs/BUILD.gn
@@ -252,6 +252,7 @@
"xfa/cfxjse_formcalc_context_embeddertest.cpp",
"xfa/cfxjse_value_embeddertest.cpp",
"xfa/cjx_hostpseudomodel_embeddertest.cpp",
+ "xfa/cjx_list_embeddertest.cpp",
]
deps += [ "../xfa/fxfa" ]
}
diff --git a/fxjs/xfa/cjx_list.cpp b/fxjs/xfa/cjx_list.cpp
index 28eb215..7c0cf23 100644
--- a/fxjs/xfa/cjx_list.cpp
+++ b/fxjs/xfa/cjx_list.cpp
@@ -62,7 +62,9 @@
auto* pBeforeNode =
ToNode(static_cast<CFXJSE_Engine*>(runtime)->ToXFAObject(params[1]));
- GetXFAList()->Insert(pNewNode, pBeforeNode);
+ if (!GetXFAList()->Insert(pNewNode, pBeforeNode))
+ return CJS_Result::Failure(JSMessage::kValueError);
+
return CJS_Result::Success();
}
diff --git a/fxjs/xfa/cjx_list_embeddertest.cpp b/fxjs/xfa/cjx_list_embeddertest.cpp
new file mode 100644
index 0000000..02450dc
--- /dev/null
+++ b/fxjs/xfa/cjx_list_embeddertest.cpp
@@ -0,0 +1,15 @@
+// Copyright 2019 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 "testing/gtest/include/gtest/gtest.h"
+#include "testing/xfa_js_embedder_test.h"
+
+class CJX_ListEmbedderTest : public XFAJSEmbedderTest {};
+
+// Should not crash.
+TEST_F(CJX_ListEmbedderTest, BUG_1263) {
+ ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
+
+ EXPECT_FALSE(Execute("nodes.insert($form,$)"));
+}
diff --git a/xfa/fxfa/parser/cxfa_arraynodelist.cpp b/xfa/fxfa/parser/cxfa_arraynodelist.cpp
index 704ad54..db36dca 100644
--- a/xfa/fxfa/parser/cxfa_arraynodelist.cpp
+++ b/xfa/fxfa/parser/cxfa_arraynodelist.cpp
@@ -27,14 +27,18 @@
m_array.push_back(pNode);
}
-void CXFA_ArrayNodeList::Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) {
+bool CXFA_ArrayNodeList::Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) {
if (!pBeforeNode) {
m_array.push_back(pNewNode);
- } else {
- auto it = std::find(m_array.begin(), m_array.end(), pBeforeNode);
- if (it != m_array.end())
- m_array.insert(it, pNewNode);
+ return true;
}
+
+ auto it = std::find(m_array.begin(), m_array.end(), pBeforeNode);
+ if (it == m_array.end())
+ return false;
+
+ m_array.insert(it, pNewNode);
+ return true;
}
void CXFA_ArrayNodeList::Remove(CXFA_Node* pNode) {
diff --git a/xfa/fxfa/parser/cxfa_arraynodelist.h b/xfa/fxfa/parser/cxfa_arraynodelist.h
index b00b4a8..238c52c 100644
--- a/xfa/fxfa/parser/cxfa_arraynodelist.h
+++ b/xfa/fxfa/parser/cxfa_arraynodelist.h
@@ -19,10 +19,10 @@
explicit CXFA_ArrayNodeList(CXFA_Document* pDocument);
~CXFA_ArrayNodeList() override;
- // From CXFA_TreeList.
+ // CXFA_TreeList:
size_t GetLength() override;
void Append(CXFA_Node* pNode) override;
- void Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override;
+ bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override;
void Remove(CXFA_Node* pNode) override;
CXFA_Node* Item(size_t iIndex) override;
diff --git a/xfa/fxfa/parser/cxfa_attachnodelist.cpp b/xfa/fxfa/parser/cxfa_attachnodelist.cpp
index e7d4c1d..8fc67cb1 100644
--- a/xfa/fxfa/parser/cxfa_attachnodelist.cpp
+++ b/xfa/fxfa/parser/cxfa_attachnodelist.cpp
@@ -29,12 +29,16 @@
m_pAttachNode->InsertChild(pNode, nullptr);
}
-void CXFA_AttachNodeList::Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) {
+bool CXFA_AttachNodeList::Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) {
+ if (pBeforeNode && pBeforeNode->GetParent() != m_pAttachNode)
+ return false;
+
CXFA_Node* pParent = pNewNode->GetParent();
if (pParent)
pParent->RemoveChild(pNewNode, true);
m_pAttachNode->InsertChild(pNewNode, pBeforeNode);
+ return true;
}
void CXFA_AttachNodeList::Remove(CXFA_Node* pNode) {
diff --git a/xfa/fxfa/parser/cxfa_attachnodelist.h b/xfa/fxfa/parser/cxfa_attachnodelist.h
index a8248e6..2b20d70 100644
--- a/xfa/fxfa/parser/cxfa_attachnodelist.h
+++ b/xfa/fxfa/parser/cxfa_attachnodelist.h
@@ -17,10 +17,10 @@
CXFA_AttachNodeList(CXFA_Document* pDocument, CXFA_Node* pAttachNode);
~CXFA_AttachNodeList() override;
- // From CXFA_TreeList.
+ // CXFA_TreeList:
size_t GetLength() override;
void Append(CXFA_Node* pNode) override;
- void Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override;
+ bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override;
void Remove(CXFA_Node* pNode) override;
CXFA_Node* Item(size_t iIndex) override;
diff --git a/xfa/fxfa/parser/cxfa_list.h b/xfa/fxfa/parser/cxfa_list.h
index bfe6508..c114801 100644
--- a/xfa/fxfa/parser/cxfa_list.h
+++ b/xfa/fxfa/parser/cxfa_list.h
@@ -19,7 +19,7 @@
virtual size_t GetLength() = 0;
virtual void Append(CXFA_Node* pNode) = 0;
- virtual void Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) = 0;
+ virtual bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) = 0;
virtual void Remove(CXFA_Node* pNode) = 0;
virtual CXFA_Node* Item(size_t iIndex) = 0;