Title: [215852] trunk
Revision
215852
Author
[email protected]
Date
2017-04-26 19:28:39 -0700 (Wed, 26 Apr 2017)

Log Message

ASSERTION FAILED: inIndex != notFound in JSC::invalidParameterInSourceAppender()
https://bugs.webkit.org/show_bug.cgi?id=170924
<rdar://problem/31721052>

Reviewed by Mark Lam.

JSTests:

* stress/error-message-for-function-base-not-found.js: Added.
(assert):
(throw.new.Error):
* stress/error-messages-for-in-operator-should-not-crash.js: Added.
(catch):

LayoutTests/imported/w3c:

* web-platform-tests/css-timing-1/cubic-bezier-timing-functions-output-expected.txt:
* web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt:
* web-platform-tests/css-timing-1/step-timing-functions-output-expected.txt:

Source/_javascript_Core:

The error message handler for "in" was searching for the literal
string "in". However, our parser incorrectly allows escaped characters
to be part of keywords. So this is parsed as "in" in JSC: "i\u006E".
It should not be parsed that way. I opened https://bugs.webkit.org/show_bug.cgi?id=171310
to address this issue.

Regardless, the error message handlers should handle unexpected text gracefully.
All functions that try to augment error messages with the goal of
providing a more textual context for the error message should use
the original error message instead of crashing when they detect
unexpected text.

This patch also changes the already buggy code that tries to find
the base of a function call. That could would fail for code like this:
"zoo.bar("/abc\)*/");". See https://bugs.webkit.org/show_bug.cgi?id=146304
It would think that the base is "z". However, the algorithm that tries
to find the base can often tell when it fails, and when it does, it should
happily return the approximate text error message instead of thinking
that the base is "z".

* runtime/ExceptionHelpers.cpp:
(JSC::functionCallBase):
(JSC::notAFunctionSourceAppender):
(JSC::invalidParameterInSourceAppender):

LayoutTests:

* js/let-syntax-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (215851 => 215852)


--- trunk/JSTests/ChangeLog	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/JSTests/ChangeLog	2017-04-27 02:28:39 UTC (rev 215852)
@@ -1,3 +1,17 @@
+2017-04-26  Saam Barati  <[email protected]>
+
+        ASSERTION FAILED: inIndex != notFound in JSC::invalidParameterInSourceAppender()
+        https://bugs.webkit.org/show_bug.cgi?id=170924
+        <rdar://problem/31721052>
+
+        Reviewed by Mark Lam.
+
+        * stress/error-message-for-function-base-not-found.js: Added.
+        (assert):
+        (throw.new.Error):
+        * stress/error-messages-for-in-operator-should-not-crash.js: Added.
+        (catch):
+
 2017-04-26  Keith Miller  <[email protected]>
 
         WebAssembly: Implement tier up

Modified: trunk/JSTests/stress/destructuring-assignment-accepts-iterables.js (215851 => 215852)


--- trunk/JSTests/stress/destructuring-assignment-accepts-iterables.js	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/JSTests/stress/destructuring-assignment-accepts-iterables.js	2017-04-27 02:28:39 UTC (rev 215852)
@@ -122,7 +122,7 @@
             return 42;
         }
     };
-}, "TypeError: [a, b, c] is not a function. (In '[a, b, c]', '[a, b, c]' is undefined)");
+}, "TypeError: undefined is not a function (near '...[a, b, c]...')");
 
 shouldThrow(function () {
     var [a, b, c] = {
@@ -130,7 +130,7 @@
             return {};
         }
     };
-}, "TypeError: [a, b, c] is not a function. (In '[a, b, c]', '[a, b, c]' is undefined)");
+}, "TypeError: undefined is not a function (near '...[a, b, c]...')");
 
 shouldThrow(function () {
     var [a, b, c] = {

Added: trunk/JSTests/stress/error-message-for-function-base-not-found.js (0 => 215852)


--- trunk/JSTests/stress/error-message-for-function-base-not-found.js	                        (rev 0)
+++ trunk/JSTests/stress/error-message-for-function-base-not-found.js	2017-04-27 02:28:39 UTC (rev 215852)
@@ -0,0 +1,30 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad");
+}
+
+{
+    let error;
+    try {
+        let foo = {};
+        foo.bar("/abc\)*/");
+    } catch(e) {
+        error = e;
+    }
+    assert(error);
+    assert(error.message ===  "undefined is not a function (near '...foo.bar(\"/abc\\)*/\")...')");
+}
+
+{
+    let error;
+    try {
+        let blah = {};
+        let x, y;
+        blah("(((");
+    } catch(e) {
+        error = e;
+    }
+
+    // This is less than ideal, but let's be aware if we ever fix it.
+    assert(error.message === "blah(\"(( is not a function. (In 'blah(\"(((\")', 'blah(\"((' is an instance of Object)");
+}

Added: trunk/JSTests/stress/error-messages-for-in-operator-should-not-crash.js (0 => 215852)


--- trunk/JSTests/stress/error-messages-for-in-operator-should-not-crash.js	                        (rev 0)
+++ trunk/JSTests/stress/error-messages-for-in-operator-should-not-crash.js	2017-04-27 02:28:39 UTC (rev 215852)
@@ -0,0 +1,11 @@
+// This test should not crash.
+
+let error = null;
+try {
+    // FIXME: We should not parse this as an "in" operation.
+    let r = "prop" i\u006E 20;
+} catch(e) {
+    error = e;
+}
+if (error.message !== "20 is not an Object.")
+    throw new Error("Bad");

Modified: trunk/LayoutTests/ChangeLog (215851 => 215852)


--- trunk/LayoutTests/ChangeLog	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/LayoutTests/ChangeLog	2017-04-27 02:28:39 UTC (rev 215852)
@@ -1,3 +1,13 @@
+2017-04-26  Saam Barati  <[email protected]>
+
+        ASSERTION FAILED: inIndex != notFound in JSC::invalidParameterInSourceAppender()
+        https://bugs.webkit.org/show_bug.cgi?id=170924
+        <rdar://problem/31721052>
+
+        Reviewed by Mark Lam.
+
+        * js/let-syntax-expected.txt:
+
 2017-04-26  Joanmarie Diggs  <[email protected]>
 
         [ATK] ARIA buttons which have a popup should be ATK_ROLE_PUSH_BUTTON; not ATK_ROLE_COMBO_BOX

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (215851 => 215852)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2017-04-27 02:28:39 UTC (rev 215852)
@@ -1,3 +1,15 @@
+2017-04-26  Saam Barati  <[email protected]>
+
+        ASSERTION FAILED: inIndex != notFound in JSC::invalidParameterInSourceAppender()
+        https://bugs.webkit.org/show_bug.cgi?id=170924
+        <rdar://problem/31721052>
+
+        Reviewed by Mark Lam.
+
+        * web-platform-tests/css-timing-1/cubic-bezier-timing-functions-output-expected.txt:
+        * web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt:
+        * web-platform-tests/css-timing-1/step-timing-functions-output-expected.txt:
+
 2017-04-26  Ryan Haddad  <[email protected]>
 
         Unreviewed, rolling out r215814.

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/cubic-bezier-timing-functions-output-expected.txt (215851 => 215852)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/cubic-bezier-timing-functions-output-expected.txt	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/cubic-bezier-timing-functions-output-expected.txt	2017-04-27 02:28:39 UTC (rev 215852)
@@ -1,6 +1,6 @@
 
-FAIL cubic-bezier easing with input progress greater than 1 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL cubic-bezier easing with input progress greater than 1 and where the tangent on the upper boundary is infinity target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL cubic-bezier easing with input progress less than 0 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL cubic-bezier easing with input progress less than 0 and where the tangent on the lower boundary is infinity target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
+FAIL cubic-bezier easing with input progress greater than 1 undefined is not a function (near '...target.animate...')
+FAIL cubic-bezier easing with input progress greater than 1 and where the tangent on the upper boundary is infinity undefined is not a function (near '...target.animate...')
+FAIL cubic-bezier easing with input progress less than 0 undefined is not a function (near '...target.animate...')
+FAIL cubic-bezier easing with input progress less than 0 and where the tangent on the lower boundary is infinity undefined is not a function (near '...target.animate...')
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt (215851 => 215852)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/frames-timing-functions-output-expected.txt	2017-04-27 02:28:39 UTC (rev 215852)
@@ -4,7 +4,7 @@
 FAIL For an input progress of 1.0, the output of a frames timing function is the final frame assert_equals: expected "100px" but got "auto"
 FAIL The number of frames is correctly reflected in the frames timing function output assert_equals: expected "0px" but got "auto"
 FAIL The number of frames is correctly reflected in the frames timing function output on CSS Transitions assert_equals: expected "0px" but got "auto"
-FAIL frames easing with input progress greater than 1 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL frames easing with input progress greater than 1.5 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL frames easing with input progress less than 0 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
+FAIL frames easing with input progress greater than 1 undefined is not a function (near '...target.animate...')
+FAIL frames easing with input progress greater than 1.5 undefined is not a function (near '...target.animate...')
+FAIL frames easing with input progress less than 0 undefined is not a function (near '...target.animate...')
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/step-timing-functions-output-expected.txt (215851 => 215852)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/step-timing-functions-output-expected.txt	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css-timing-1/step-timing-functions-output-expected.txt	2017-04-27 02:28:39 UTC (rev 215852)
@@ -1,8 +1,8 @@
 
-FAIL step-start easing with input progress greater than 1 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL step-end easing with input progress greater than 1 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL step-end easing with input progress greater than 2 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL step-start easing with input progress less than 0 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL step-start easing with input progress less than -1 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
-FAIL step-end easing with input progress less than 0 target.animate is not a function. (In 'target.animate', 'target.animate' is undefined)
+FAIL step-start easing with input progress greater than 1 undefined is not a function (near '...target.animate...')
+FAIL step-end easing with input progress greater than 1 undefined is not a function (near '...target.animate...')
+FAIL step-end easing with input progress greater than 2 undefined is not a function (near '...target.animate...')
+FAIL step-start easing with input progress less than 0 undefined is not a function (near '...target.animate...')
+FAIL step-start easing with input progress less than -1 undefined is not a function (near '...target.animate...')
+FAIL step-end easing with input progress less than 0 undefined is not a function (near '...target.animate...')
 

Modified: trunk/LayoutTests/js/let-syntax-expected.txt (215851 => 215852)


--- trunk/LayoutTests/js/let-syntax-expected.txt	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/LayoutTests/js/let-syntax-expected.txt	2017-04-27 02:28:39 UTC (rev 215852)
@@ -404,7 +404,7 @@
 SyntaxError: Cannot use abbreviated destructuring syntax for keyword 'let'.
 SyntaxError: Cannot use abbreviated destructuring syntax for keyword 'let'.
 PASS Has syntax error: ''use strict'; var {let} = 40;'
-TypeError: [let] is not a function. (In '[let]', '[let]' is undefined)
+TypeError: undefined is not a function (near '...[let]...')
 PASS Does not have syntax error: 'var [let] = 40;'
 SyntaxError: Cannot use 'let' as a variable name in strict mode.
 SyntaxError: Cannot use 'let' as a variable name in strict mode.

Modified: trunk/Source/_javascript_Core/ChangeLog (215851 => 215852)


--- trunk/Source/_javascript_Core/ChangeLog	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-04-27 02:28:39 UTC (rev 215852)
@@ -1,3 +1,36 @@
+2017-04-26  Saam Barati  <[email protected]>
+
+        ASSERTION FAILED: inIndex != notFound in JSC::invalidParameterInSourceAppender()
+        https://bugs.webkit.org/show_bug.cgi?id=170924
+        <rdar://problem/31721052>
+
+        Reviewed by Mark Lam.
+
+        The error message handler for "in" was searching for the literal
+        string "in". However, our parser incorrectly allows escaped characters
+        to be part of keywords. So this is parsed as "in" in JSC: "i\u006E".
+        It should not be parsed that way. I opened https://bugs.webkit.org/show_bug.cgi?id=171310
+        to address this issue.
+        
+        Regardless, the error message handlers should handle unexpected text gracefully.
+        All functions that try to augment error messages with the goal of
+        providing a more textual context for the error message should use
+        the original error message instead of crashing when they detect
+        unexpected text.
+        
+        This patch also changes the already buggy code that tries to find
+        the base of a function call. That could would fail for code like this:
+        "zoo.bar("/abc\)*/");". See https://bugs.webkit.org/show_bug.cgi?id=146304
+        It would think that the base is "z". However, the algorithm that tries
+        to find the base can often tell when it fails, and when it does, it should
+        happily return the approximate text error message instead of thinking
+        that the base is "z".
+
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::functionCallBase):
+        (JSC::notAFunctionSourceAppender):
+        (JSC::invalidParameterInSourceAppender):
+
 2017-04-26  Keith Miller  <[email protected]>
 
         WebAssembly: Implement tier up

Modified: trunk/Source/_javascript_Core/runtime/ExceptionHelpers.cpp (215851 => 215852)


--- trunk/Source/_javascript_Core/runtime/ExceptionHelpers.cpp	2017-04-27 01:26:08 UTC (rev 215851)
+++ trunk/Source/_javascript_Core/runtime/ExceptionHelpers.cpp	2017-04-27 02:28:39 UTC (rev 215852)
@@ -127,7 +127,7 @@
         // and their closing parenthesis, the text range passed into the message appender 
         // will not inlcude the text in between these parentheses, it will just be the desired
         // text that precedes the parentheses.
-        return sourceText;
+        return String();
     }
 
     unsigned parenStack = 1;
@@ -135,26 +135,32 @@
     idx -= 1;
     // Note that we're scanning text right to left instead of the more common left to right, 
     // so syntax detection is backwards.
-    while (parenStack > 0) {
+    while (parenStack && idx) {
         UChar curChar = sourceText[idx];
-        if (isInMultiLineComment)  {
-            if (idx > 0 && curChar == '*' && sourceText[idx - 1] == '/') {
+        if (isInMultiLineComment) {
+            if (curChar == '*' && sourceText[idx - 1] == '/') {
                 isInMultiLineComment = false;
-                idx -= 1;
+                --idx;
             }
         } else if (curChar == '(')
-            parenStack -= 1;
+            --parenStack;
         else if (curChar == ')')
-            parenStack += 1;
-        else if (idx > 0 && curChar == '/' && sourceText[idx - 1] == '*') {
+            ++parenStack;
+        else if (curChar == '/' && sourceText[idx - 1] == '*') {
             isInMultiLineComment = true;
-            idx -= 1;
+            --idx;
         }
 
-        if (!idx)
-            break;
+        if (idx)
+            --idx;
+    }
 
-        idx -= 1;
+    if (parenStack) {
+        // As noted in the FIXME at the top of this function, there are bugs
+        // in the above string processing. This algorithm is mostly best effort
+        // and it works for most JS text in practice. However, if we determine
+        // that the algorithm failed, we should just return the empty value.
+        return String();
     }
 
     return sourceText.left(idx + 1);
@@ -177,6 +183,8 @@
         displayValue = StringView(originalMessage.characters16(), notAFunctionIndex - 1);
 
     String base = functionCallBase(sourceText);
+    if (!base)
+        return defaultApproximateSourceError(originalMessage, sourceText);
     StringBuilder builder;
     builder.append(base);
     builder.appendLiteral(" is not a function. (In '");
@@ -205,7 +213,12 @@
 
     ASSERT(occurrence == ErrorInstance::FoundExactSource);
     auto inIndex = sourceText.reverseFind("in");
-    RELEASE_ASSERT(inIndex != notFound);
+    if (inIndex == notFound) {
+        // This should basically never happen, since JS code must use the literal
+        // text "in" for the `in` operation. However, if we fail to find "in"
+        // for any reason, just fail gracefully.
+        return originalMessage;
+    }
     if (sourceText.find("in") != inIndex)
         return makeString(originalMessage, " (evaluating '", sourceText, "')");
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to