Title: [265373] trunk
Revision
265373
Author
msab...@apple.com
Date
2020-08-07 08:51:33 -0700 (Fri, 07 Aug 2020)

Log Message

RegExp sticky not matching alternates correctly, ignoring lastIndex requirement
https://bugs.webkit.org/show_bug.cgi?id=214181

Reviewed by Yusuke Suzuki.

JSTests:

New test.

* stress/regexp-sticky-tests.js: Added.
(assert):

Source/_javascript_Core:

In the YARR JIT, we need to check for sticky patterns before checking for fixed character
terms when backtracking.  The YARR interpreter doesn't have this issue.

* yarr/YarrJIT.cpp:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (265372 => 265373)


--- trunk/JSTests/ChangeLog	2020-08-07 14:49:09 UTC (rev 265372)
+++ trunk/JSTests/ChangeLog	2020-08-07 15:51:33 UTC (rev 265373)
@@ -1,3 +1,15 @@
+2020-08-07  Michael Saboff  <msab...@apple.com>
+
+        RegExp sticky not matching alternates correctly, ignoring lastIndex requirement
+        https://bugs.webkit.org/show_bug.cgi?id=214181
+
+        Reviewed by Yusuke Suzuki.
+
+        New test.
+
+        * stress/regexp-sticky-tests.js: Added.
+        (assert):
+
 2020-08-07  Paulo Matos  <pma...@igalia.com>
 
         Skip test on ARM32 - test is flaky in mini-mode

Added: trunk/JSTests/stress/regexp-sticky-tests.js (0 => 265373)


--- trunk/JSTests/stress/regexp-sticky-tests.js	                        (rev 0)
+++ trunk/JSTests/stress/regexp-sticky-tests.js	2020-08-07 15:51:33 UTC (rev 265373)
@@ -0,0 +1,100 @@
+// Verify sticky RegExp matching.
+
+function assert(b)
+{
+    if (!b)
+        throw new Error("Bad assertion");
+}
+
+let re = new RegExp("a|aa", "y");
+let s1 = "_aaba";
+let m = null;
+
+// First character, '_', shouldn't match.
+assert(re.exec(s1) === null);
+assert(re.lastIndex === 0);
+
+// Second character, 'a', should match and we'll advance to the next character.
+re.lastIndex = 1;
+m = re.exec(s1);
+assert(m[0] === 'a');
+assert(re.lastIndex === 2);
+
+// Third character, 'a', should match and we'll advance to the next character.
+m = re.exec(s1);
+assert(m[0] === 'a');
+assert(re.lastIndex === 3);
+
+// Fourth character, 'b', shouldn't match.
+m = re.exec(s1);
+assert(m === null);
+assert(re.lastIndex === 0);
+
+// Fifth character, 'a', should match and we'll advance past the last character.
+re.lastIndex = 4;
+m = re.exec(s1);
+assert(m[0] === 'a');
+assert(re.lastIndex === 5);
+
+// We shoudn't match starting past the last character.
+m = re.exec(s1);
+assert(m === null);
+
+re = new RegExp("ax|a", "y");
+// First character, '_', shouldn't match.
+assert(re.exec(s1) === null);
+assert(re.lastIndex === 0);
+
+// Second character, 'a', should match and we'll advance to the next character.
+re.lastIndex = 1;
+m = re.exec(s1);
+assert(m[0] === 'a');
+assert(re.lastIndex === 2);
+
+// Third character, 'a', should match and we'll advance to the next character.
+m = re.exec(s1);
+assert(m[0] === 'a');
+assert(re.lastIndex === 3);
+
+// Fourth character, 'b', shouldn't match.
+m = re.exec(s1);
+assert(m === null);
+assert(re.lastIndex === 0);
+
+// Fifth character, 'a', should match and we'll advance past the last character.
+re.lastIndex = 4;
+m = re.exec(s1);
+assert(m[0] === 'a');
+assert(re.lastIndex === 5);
+
+// We shoudn't match starting past the last character.
+m = re.exec(s1);
+assert(m === null);
+
+re = new RegExp("aa|a", "y");
+
+re.lastIndex = 0;
+// First character, '_', shouldn't match.
+assert(re.exec(s1) === null);
+assert(re.lastIndex === 0);
+
+// Second and third characters, 'aa', should match and we'll advance past them.
+re.lastIndex = 1;
+m = re.exec(s1);
+assert(m[0] === 'aa');
+assert(re.lastIndex === 3);
+
+// Fourth character, 'b', shouldn't match.
+m = re.exec(s1);
+assert(m === null);
+assert(re.lastIndex === 0);
+
+// Fifth character, 'a', should match and we'll advance past the last character.
+re.lastIndex = 4;
+m = re.exec(s1);
+assert(m[0] === 'a');
+assert(re.lastIndex === 5);
+
+// We shoudn't match starting past the last character.
+m = re.exec(s1);
+assert(m === null);

Modified: trunk/Source/_javascript_Core/ChangeLog (265372 => 265373)


--- trunk/Source/_javascript_Core/ChangeLog	2020-08-07 14:49:09 UTC (rev 265372)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-08-07 15:51:33 UTC (rev 265373)
@@ -1,3 +1,15 @@
+2020-08-07  Michael Saboff  <msab...@apple.com>
+
+        RegExp sticky not matching alternates correctly, ignoring lastIndex requirement
+        https://bugs.webkit.org/show_bug.cgi?id=214181
+
+        Reviewed by Yusuke Suzuki.
+
+        In the YARR JIT, we need to check for sticky patterns before checking for fixed character
+        terms when backtracking.  The YARR interpreter doesn't have this issue.
+
+        * yarr/YarrJIT.cpp:
+
 2020-08-05  Tim Horton  <timothy_hor...@apple.com>
 
         Remove all references to non-existent 10.16

Modified: trunk/Source/_javascript_Core/yarr/YarrJIT.cpp (265372 => 265373)


--- trunk/Source/_javascript_Core/yarr/YarrJIT.cpp	2020-08-07 14:49:09 UTC (rev 265372)
+++ trunk/Source/_javascript_Core/yarr/YarrJIT.cpp	2020-08-07 15:51:33 UTC (rev 265373)
@@ -2821,17 +2821,17 @@
                 if (onceThrough)
                     m_backtrackingState.linkTo(endOp.m_reentry, this);
                 else {
-                    // If we don't need to move the input poistion, and the pattern has a fixed size
-                    // (in which case we omit the store of the start index until the pattern has matched)
-                    // then we can just link the backtrack out of the last alternative straight to the
-                    // head of the first alternative.
-                    if (m_pattern.m_body->m_hasFixedSize
+                    if (m_pattern.sticky() && m_ops[op.m_nextOp].m_op == OpBodyAlternativeEnd) {
+                        // It is a sticky pattern and the last alternative failed, jump to the end.
+                        m_backtrackingState.takeBacktracksToJumpList(lastStickyAlternativeFailures, this);
+                    } else if (m_pattern.m_body->m_hasFixedSize
                         && (alternative->m_minimumSize > beginOp->m_alternative->m_minimumSize)
-                        && (alternative->m_minimumSize - beginOp->m_alternative->m_minimumSize == 1))
+                        && (alternative->m_minimumSize - beginOp->m_alternative->m_minimumSize == 1)) {
+                        // If we don't need to move the input position, and the pattern has a fixed size
+                        // (in which case we omit the store of the start index until the pattern has matched)
+                        // then we can just link the backtrack out of the last alternative straight to the
+                        // head of the first alternative.
                         m_backtrackingState.linkTo(beginOp->m_reentry, this);
-                    else if (m_pattern.sticky() && m_ops[op.m_nextOp].m_op == OpBodyAlternativeEnd) {
-                        // It is a sticky pattern and the last alternative failed, jump to the end.
-                        m_backtrackingState.takeBacktracksToJumpList(lastStickyAlternativeFailures, this);
                     } else {
                         // We need to generate a trampoline of code to execute before looping back
                         // around to the first alternative.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to