Handle CFDE_TextEditEngine delegate unexpectedly changing text.
JavaScript might run and change the value into which text
is about to be inserted, so recheck boundaries before
continuing.
Bug: chromium:976753
Change-Id: I7d5e8cf0ccc3be881ab7303fafad53c54d3f6ec2
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/56630
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/testing/resources/javascript/xfa_specific/bug_976753.evt b/testing/resources/javascript/xfa_specific/bug_976753.evt
new file mode 100644
index 0000000..beda23a
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/bug_976753.evt
@@ -0,0 +1,6 @@
+mousedown,left,200,95
+mouseup,left,200,95
+charcode,72
+charcode,72
+charcode,72
+charcode,72
diff --git a/testing/resources/javascript/xfa_specific/bug_976753.in b/testing/resources/javascript/xfa_specific/bug_976753.in
new file mode 100644
index 0000000..c9cf91c
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/bug_976753.in
@@ -0,0 +1,42 @@
+{{header}}
+{{include ../../xfa_catalog_1_0.fragment}}
+{{include ../../xfa_object_2_0.fragment}}
+{{include ../../xfa_preamble_3_0.fragment}}
+{{include ../../xfa_config_4_0.fragment}}
+{{object 5 0}} <<
+ {{steamlen}}
+>>
+stream
+<template xmlns="http://www.xfa.org/schema/xfa-template/3.3/">
+ <subform name="form1" layout="tb" locale="en_US" restoreState="auto">
+ <event activity="docReady" ref="$form">
+ <script>
+ Field0.rawValue = "dog"
+ </script>
+ </event>
+ <field x="0" y="0" w="1000pt" h="1000pt" name="Field0">
+ <event activity="change">
+ <script contentType="application/x-javascript">
+ xfa.host.setFocus('form1.Field1');
+ </script>
+ </event>
+ </field>
+ <field x="100pt" y="100pt" w="100pt" h="100pt" name="Field1">
+ <event activity="enter" listen="refAndDescendents">
+ <script contentType="application/x-javascript">
+ xfa.host.setFocus('form1.Field0')
+ Field0.rawValue="m9";
+ </script>
+ </event>
+ </field>
+ </subform>
+</template>
+endstream
+endobj
+{{include ../../xfa_locale_6_0.fragment}}
+{{include ../../xfa_postamble_7_0.fragment}}
+{{include ../../xfa_pages_8_0.fragment}}
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/xfa/fde/cfde_texteditengine.cpp b/xfa/fde/cfde_texteditengine.cpp
index 8dfc532..297724a 100644
--- a/xfa/fde/cfde_texteditengine.cpp
+++ b/xfa/fde/cfde_texteditengine.cpp
@@ -8,6 +8,7 @@
#include <algorithm>
#include <limits>
+#include <utility>
#include "third_party/base/ptr_util.h"
#include "xfa/fde/cfde_textout.h"
@@ -268,8 +269,8 @@
WideString text = request_text;
if (text.GetLength() == 0)
return;
- if (idx > text_length_)
- idx = text_length_;
+
+ idx = std::min(idx, text_length_);
TextChange change;
change.selection_start = idx;
@@ -287,9 +288,12 @@
text = change.text;
idx = change.selection_start;
- // JS extended the selection, so delete it before we insert.
+ // Delegate extended the selection, so delete it before we insert.
if (change.selection_end != change.selection_start)
DeleteSelectedText(RecordOperation::kSkipRecord);
+
+ // Delegate may have changed text entirely, recheck.
+ idx = std::min(idx, text_length_);
}
size_t length = text.GetLength();
@@ -848,8 +852,13 @@
if (change.cancelled)
return WideString();
+ // Delegate may have changed the selection range.
start_idx = change.selection_start;
length = change.selection_end - change.selection_start;
+
+ // Delegate may have changed text entirely, recheck.
+ if (start_idx >= text_length_)
+ return WideString();
}
length = std::min(length, text_length_ - start_idx);