Title: [283232] trunk
Revision
283232
Author
[email protected]
Date
2021-09-29 10:03:29 -0700 (Wed, 29 Sep 2021)

Log Message

Code inside strength reduction can incorrectly prove that we know what lastIndex is
https://bugs.webkit.org/show_bug.cgi?id=230802
<rdar://problem/83543699>

Reviewed by Mark Lam.

JSTests:

* stress/dont-fold-regexp-exec-when-we-dont-know-last-index-and-regexp-is-constant.js: Added.
(assert):
(let.reg.RegExp.foo.g.doExec):
(noInline.doExec):

Source/_javascript_Core:

The phase was searching backwards in the graph to see if it found the RegExp
node. However, the RegExp node might be a JSConstant. Hence, the program
didn't allocate it. So we can't assume that we know what the lastIndex is.
We were incorrectly assuming it was "0" in a program like this:
a: JSConstant(RegExp)
b: RegExpExec(@a)

And we assumed we're invoking RegExpExec with lastIndex is 0, because we found
our RegExp in a backwards search. This is likely because we're also matching
NewRegExp nodes, in which case, it is valid to say lastIndex is 0.

This caused us to return a constant value that would've been the exec
result had we invoked it with a NewRegExpNode.

* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::run):
(JSC::DFG::StrengthReductionPhase::handleNode):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (283231 => 283232)


--- trunk/JSTests/ChangeLog	2021-09-29 16:56:07 UTC (rev 283231)
+++ trunk/JSTests/ChangeLog	2021-09-29 17:03:29 UTC (rev 283232)
@@ -1,5 +1,18 @@
 2021-09-29  Saam Barati  <[email protected]>
 
+        Code inside strength reduction can incorrectly prove that we know what lastIndex is
+        https://bugs.webkit.org/show_bug.cgi?id=230802
+        <rdar://problem/83543699>
+
+        Reviewed by Mark Lam.
+
+        * stress/dont-fold-regexp-exec-when-we-dont-know-last-index-and-regexp-is-constant.js: Added.
+        (assert):
+        (let.reg.RegExp.foo.g.doExec):
+        (noInline.doExec):
+
+2021-09-29  Saam Barati  <[email protected]>
+
         DoesGCCheck does not use enough bits for nodeIndex
         https://bugs.webkit.org/show_bug.cgi?id=230915
         <rdar://83297515>

Added: trunk/JSTests/stress/dont-fold-regexp-exec-when-we-dont-know-last-index-and-regexp-is-constant.js (0 => 283232)


--- trunk/JSTests/stress/dont-fold-regexp-exec-when-we-dont-know-last-index-and-regexp-is-constant.js	                        (rev 0)
+++ trunk/JSTests/stress/dont-fold-regexp-exec-when-we-dont-know-last-index-and-regexp-is-constant.js	2021-09-29 17:03:29 UTC (rev 283232)
@@ -0,0 +1,19 @@
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+
+let reg = RegExp(/foo/g)
+function doExec() {
+    return reg.exec("-foo");
+}
+noInline(doExec)
+
+for (let i = 0; i < 1000; ++i) {
+    let r = doExec();
+    if ((i % 2) === 0)
+        assert(r[0] === "foo");
+    else
+        assert(r === null);
+}
+

Modified: trunk/Source/_javascript_Core/ChangeLog (283231 => 283232)


--- trunk/Source/_javascript_Core/ChangeLog	2021-09-29 16:56:07 UTC (rev 283231)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-09-29 17:03:29 UTC (rev 283232)
@@ -1,3 +1,29 @@
+2021-09-29  Saam Barati  <[email protected]>
+
+        Code inside strength reduction can incorrectly prove that we know what lastIndex is
+        https://bugs.webkit.org/show_bug.cgi?id=230802
+        <rdar://problem/83543699>
+
+        Reviewed by Mark Lam.
+
+        The phase was searching backwards in the graph to see if it found the RegExp
+        node. However, the RegExp node might be a JSConstant. Hence, the program
+        didn't allocate it. So we can't assume that we know what the lastIndex is.
+        We were incorrectly assuming it was "0" in a program like this:
+        a: JSConstant(RegExp)
+        b: RegExpExec(@a)
+        
+        And we assumed we're invoking RegExpExec with lastIndex is 0, because we found
+        our RegExp in a backwards search. This is likely because we're also matching
+        NewRegExp nodes, in which case, it is valid to say lastIndex is 0.
+        
+        This caused us to return a constant value that would've been the exec
+        result had we invoked it with a NewRegExpNode.
+
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::run):
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+
 2021-09-29  Yusuke Suzuki  <[email protected]>
 
         [JSC] Use FixedVector in JITConstantPool

Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (283231 => 283232)


--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2021-09-29 16:56:07 UTC (rev 283231)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2021-09-29 17:03:29 UTC (rev 283232)
@@ -491,11 +491,13 @@
 
             Node* regExpObjectNode = nullptr;
             RegExp* regExp = nullptr;
+            bool regExpObjectNodeIsConstant = false;
             if (m_node->op() == RegExpExec || m_node->op() == RegExpTest || m_node->op() == RegExpMatchFast) {
                 regExpObjectNode = m_node->child2().node();
-                if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(vm()))
+                if (RegExpObject* regExpObject = regExpObjectNode->dynamicCastConstant<RegExpObject*>(vm())) {
                     regExp = regExpObject->regExp();
-                else if (regExpObjectNode->op() == NewRegexp)
+                    regExpObjectNodeIsConstant = true;
+                } else if (regExpObjectNode->op() == NewRegexp)
                     regExp = regExpObjectNode->castOperand<RegExp*>();
                 else {
                     if (verbose)
@@ -545,6 +547,8 @@
                 for (unsigned otherNodeIndex = m_nodeIndex; otherNodeIndex--;) {
                     Node* otherNode = m_block->at(otherNodeIndex);
                     if (otherNode == regExpObjectNode) {
+                        if (regExpObjectNodeIsConstant)
+                            break;
                         lastIndex = 0;
                         break;
                     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to