Title: [208698] trunk
Revision
208698
Author
[email protected]
Date
2016-11-14 11:26:20 -0800 (Mon, 14 Nov 2016)

Log Message

RegExpObject::exec/match should handle errors gracefully.
https://bugs.webkit.org/show_bug.cgi?id=155145
<rdar://problem/27435934>

Reviewed by Keith Miller.

JSTests:

* stress/regexp-prototype-exec-on-too-long-rope.js: Added.
* stress/regexp-prototype-match-on-too-long-rope.js: Added.
* stress/regexp-prototype-test-on-too-long-rope.js: Added.

Source/_javascript_Core:

1. Added some missing exception checks to RegExpObject::execInline() and
   RegExpObject::matchInline().
2. Updated related code to work with ExceptionScope verification requirements.

* dfg/DFGOperations.cpp:
* runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncTestFast):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncMatchFast):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (208697 => 208698)


--- trunk/JSTests/ChangeLog	2016-11-14 19:16:02 UTC (rev 208697)
+++ trunk/JSTests/ChangeLog	2016-11-14 19:26:20 UTC (rev 208698)
@@ -1,5 +1,17 @@
 2016-11-14  Mark Lam  <[email protected]>
 
+        RegExpObject::exec/match should handle errors gracefully.
+        https://bugs.webkit.org/show_bug.cgi?id=155145
+        <rdar://problem/27435934>
+
+        Reviewed by Keith Miller.
+
+        * stress/regexp-prototype-exec-on-too-long-rope.js: Added.
+        * stress/regexp-prototype-match-on-too-long-rope.js: Added.
+        * stress/regexp-prototype-test-on-too-long-rope.js: Added.
+
+2016-11-14  Mark Lam  <[email protected]>
+
         Enhance run-jsc-stress-test script to allow optional test specific options to be added for all test run configurations.
         https://bugs.webkit.org/show_bug.cgi?id=164695
 

Added: trunk/JSTests/stress/regexp-prototype-exec-on-too-long-rope.js (0 => 208698)


--- trunk/JSTests/stress/regexp-prototype-exec-on-too-long-rope.js	                        (rev 0)
+++ trunk/JSTests/stress/regexp-prototype-exec-on-too-long-rope.js	2016-11-14 19:26:20 UTC (rev 208698)
@@ -0,0 +1,32 @@
+//@ if $buildType == "debug" then runFTLNoCJIT("--maxSingleAllocationSize=20000000") else skip end
+
+function shouldEqual(actual, expected) {
+    if (actual != expected) {
+        throw "ERROR: expect " + expected + ", actual " + actual;
+    }
+}
+
+s0 = "";
+s1 = "NaNxxxxx";
+
+try {
+    for (var count = 0; count < 27; count++) {
+        var oldS1 = s1;
+        s1 += s1;
+        s0 = oldS1;
+    }
+} catch (e) { }
+
+try {
+    s1 += s0;
+} catch (e) { }
+
+var exception;
+try {
+    /x/.exec(s1);
+} catch (e) {
+    exception = e;
+}
+
+shouldEqual(exception, "Error: Out of memory");
+

Added: trunk/JSTests/stress/regexp-prototype-match-on-too-long-rope.js (0 => 208698)


--- trunk/JSTests/stress/regexp-prototype-match-on-too-long-rope.js	                        (rev 0)
+++ trunk/JSTests/stress/regexp-prototype-match-on-too-long-rope.js	2016-11-14 19:26:20 UTC (rev 208698)
@@ -0,0 +1,32 @@
+//@ if $buildType == "debug" then runFTLNoCJIT("--maxSingleAllocationSize=20000000") else skip end
+
+function shouldEqual(actual, expected) {
+    if (actual != expected) {
+        throw "ERROR: expect " + expected + ", actual " + actual;
+    }
+}
+
+s0 = "";
+s1 = "NaNxxxxx";
+
+try {
+    for (var count = 0; count < 27; count++) {
+        var oldS1 = s1;
+        s1 += s1;
+        s0 = oldS1;
+    }
+} catch (e) { }
+
+try {
+    s1 += s0;
+} catch (e) { }
+
+var exception;
+try {
+    /x/[Symbol.match](s1);
+} catch (e) {
+    exception = e;
+}
+
+shouldEqual(exception, "Error: Out of memory");
+

Added: trunk/JSTests/stress/regexp-prototype-test-on-too-long-rope.js (0 => 208698)


--- trunk/JSTests/stress/regexp-prototype-test-on-too-long-rope.js	                        (rev 0)
+++ trunk/JSTests/stress/regexp-prototype-test-on-too-long-rope.js	2016-11-14 19:26:20 UTC (rev 208698)
@@ -0,0 +1,32 @@
+//@ if $buildType == "debug" then runFTLNoCJIT("--maxSingleAllocationSize=20000000") else skip end
+
+function shouldEqual(actual, expected) {
+    if (actual != expected) {
+        throw "ERROR: expect " + expected + ", actual " + actual;
+    }
+}
+
+s0 = "";
+s1 = "NaNxxxxx";
+
+try {
+    for (var count = 0; count < 27; count++) {
+        var oldS1 = s1;
+        s1 += s1;
+        s0 = oldS1;
+    }
+} catch (e) { }
+
+try {
+    s1 += s0;
+} catch (e) { }
+
+var exception;
+try {
+    /x/.test(s1);
+} catch (e) {
+    exception = e;
+}
+
+shouldEqual(exception, "Error: Out of memory");
+

Modified: trunk/Source/_javascript_Core/ChangeLog (208697 => 208698)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-14 19:16:02 UTC (rev 208697)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-14 19:26:20 UTC (rev 208698)
@@ -1,3 +1,24 @@
+2016-11-14  Mark Lam  <[email protected]>
+
+        RegExpObject::exec/match should handle errors gracefully.
+        https://bugs.webkit.org/show_bug.cgi?id=155145
+        <rdar://problem/27435934>
+
+        Reviewed by Keith Miller.
+
+        1. Added some missing exception checks to RegExpObject::execInline() and
+           RegExpObject::matchInline().
+        2. Updated related code to work with ExceptionScope verification requirements.
+
+        * dfg/DFGOperations.cpp:
+        * runtime/RegExpObjectInlines.h:
+        (JSC::RegExpObject::execInline):
+        (JSC::RegExpObject::matchInline):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncTestFast):
+        (JSC::regExpProtoFuncExec):
+        (JSC::regExpProtoFuncMatchFast):
+
 2016-11-13  Mark Lam  <[email protected]>
 
         Add debugging facility to limit the max single allocation size.

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (208697 => 208698)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-11-14 19:16:02 UTC (rev 208697)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-11-14 19:26:20 UTC (rev 208698)
@@ -792,12 +792,15 @@
     
     VM& vm = globalObject->vm();
     NativeCallFrameTracer tracer(&vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
     
     JSValue argument = JSValue::decode(encodedArgument);
 
     JSString* input = argument.toStringOrNull(exec);
+    ASSERT(!!scope.exception() == !input);
     if (!input)
-        return JSValue::encode(jsUndefined());
+        return encodedJSValue();
+    scope.release();
     return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
 }
         
@@ -816,8 +819,10 @@
         return throwVMTypeError(exec, scope);
 
     JSString* input = argument.toStringOrNull(exec);
+    ASSERT(!!scope.exception() == !input);
     if (!input)
         return JSValue::encode(jsUndefined());
+    scope.release();
     return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
 }
         
@@ -863,8 +868,10 @@
     }
 
     JSString* input = argument.toStringOrNull(exec);
+    ASSERT(!!scope.exception() == !input);
     if (!input)
         return false;
+    scope.release();
     return asRegExpObject(base)->test(exec, globalObject, input);
 }
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h (208697 => 208698)


--- trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h	2016-11-14 19:16:02 UTC (rev 208697)
+++ trunk/Source/_javascript_Core/runtime/RegExpObjectInlines.h	2016-11-14 19:26:20 UTC (rev 208698)
@@ -57,10 +57,13 @@
 
 JSValue RegExpObject::execInline(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     RegExp* regExp = this->regExp();
     RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
-    String input = string->value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
-    VM& vm = globalObject->vm();
+    String input = string->value(exec);
+    RETURN_IF_EXCEPTION(scope, JSValue());
 
     bool globalOrSticky = regExp->globalOrSticky();
 
@@ -91,10 +94,14 @@
 MatchResult RegExpObject::matchInline(
     ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     RegExp* regExp = this->regExp();
     RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
-    String input = string->value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
-    VM& vm = globalObject->vm();
+    String input = string->value(exec);
+    RETURN_IF_EXCEPTION(scope, MatchResult());
+
     if (!regExp->global() && !regExp->sticky())
         return regExpConstructor->performMatch(vm, regExp, string, input, 0);
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (208697 => 208698)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-11-14 19:16:02 UTC (rev 208697)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-11-14 19:26:20 UTC (rev 208698)
@@ -105,8 +105,10 @@
     if (!thisValue.inherits(RegExpObject::info()))
         return throwVMTypeError(exec, scope);
     JSString* string = exec->argument(0).toStringOrNull(exec);
+    ASSERT(!!scope.exception() == !string);
     if (!string)
         return JSValue::encode(jsUndefined());
+    scope.release();
     return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->test(exec, exec->lexicalGlobalObject(), string)));
 }
 
@@ -119,8 +121,10 @@
     if (!thisValue.inherits(RegExpObject::info()))
         return throwVMTypeError(exec, scope, "Builtin RegExp exec can only be called on a RegExp object");
     JSString* string = exec->argument(0).toStringOrNull(exec);
+    ASSERT(!!scope.exception() == !string);
     if (!string)
         return JSValue::encode(jsUndefined());
+    scope.release();
     return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->lexicalGlobalObject(), string));
 }
 
@@ -133,10 +137,14 @@
     if (!thisValue.inherits(RegExpObject::info()))
         return throwVMTypeError(exec, scope);
     JSString* string = exec->argument(0).toStringOrNull(exec);
+    ASSERT(!!scope.exception() == !string);
     if (!string)
-        return JSValue::encode(jsUndefined());
-    if (!asRegExpObject(thisValue)->regExp()->global())
+        return encodedJSValue();
+    if (!asRegExpObject(thisValue)->regExp()->global()) {
+        scope.release();
         return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->lexicalGlobalObject(), string));
+    }
+    scope.release();
     return JSValue::encode(asRegExpObject(thisValue)->matchGlobal(exec, exec->lexicalGlobalObject(), string));
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to