Title: [204206] trunk
Revision
204206
Author
sbar...@apple.com
Date
2016-08-05 17:46:50 -0700 (Fri, 05 Aug 2016)

Log Message

various math operations don't properly check for an exception after calling toNumber() on the lhs
https://bugs.webkit.org/show_bug.cgi?id=160154

Reviewed by Mark Lam.

JSTests:

* stress/to-number-throws-correct-exception.js: Added.
(test.let.test.runTest.):
(test.let.test.runTest.get f):
(test.let.test.runTest):
(test.let.test):
(test):
(test2.runTest.):
(test2.runTest.get f):
(test2.runTest):
(test2):

Source/_javascript_Core:

We must check for an exception after calling toNumber() on the lhs
because this can throw an exception. If we called toNumber() on
the rhs without first checking for an exception after the toNumber()
on the lhs, this can lead us to execute effectful code or deviate
from the standard in subtle ways. I fixed this bug in various places
by always checking for an exception after calling toNumber() on the
lhs for the various bit and arithmetic operations.

This patch also found a commutativity bug inside DFGStrengthReduction.
We could end up commuting the lhs and rhs of say an "|" _expression_
even when the lhs/rhs may not be numbers. This is wrong because
executing toNumber() on the lhs/rhs has strict ordering guarantees
by the specification and is observable by user programs.

* dfg/DFGOperations.cpp:
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleCommutativity):
* jit/JITOperations.cpp:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/Operations.cpp:
(JSC::jsAddSlowCase):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (204205 => 204206)


--- trunk/JSTests/ChangeLog	2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/JSTests/ChangeLog	2016-08-06 00:46:50 UTC (rev 204206)
@@ -1,5 +1,23 @@
 2016-08-05  Saam Barati  <sbar...@apple.com>
 
+        various math operations don't properly check for an exception after calling toNumber() on the lhs
+        https://bugs.webkit.org/show_bug.cgi?id=160154
+
+        Reviewed by Mark Lam.
+
+        * stress/to-number-throws-correct-exception.js: Added.
+        (test.let.test.runTest.):
+        (test.let.test.runTest.get f):
+        (test.let.test.runTest):
+        (test.let.test):
+        (test):
+        (test2.runTest.):
+        (test2.runTest.get f):
+        (test2.runTest):
+        (test2):
+
+2016-08-05  Saam Barati  <sbar...@apple.com>
+
         Assertion failure when accessing TDZ variable in catch through eval
         https://bugs.webkit.org/show_bug.cgi?id=160554
 

Added: trunk/JSTests/stress/to-number-throws-correct-exception.js (0 => 204206)


--- trunk/JSTests/stress/to-number-throws-correct-exception.js	                        (rev 0)
+++ trunk/JSTests/stress/to-number-throws-correct-exception.js	2016-08-06 00:46:50 UTC (rev 204206)
@@ -0,0 +1,121 @@
+function test(op) {
+    let test = `
+        function runTest(iters) {
+            let shouldThrow = false;
+            let a = {
+                valueOf() { 
+                    if (shouldThrow)
+                        throw "a";
+                    return 0;
+                }
+            };
+            let {proxy: b, revoke} = Proxy.revocable({}, {
+                get: function(target, prop) {
+                    if (prop === "valueOf") {
+                        if (shouldThrow)
+                            throw new Error("Should not be here!");
+                        return function() {
+                            return 0;
+                        }
+                    }
+                }
+            });
+            function f(a, b) {
+                return a ${op} b;
+            }
+            noInline(f);
+            for (let i = 0; i < iters; i++) {
+                f(a, b);
+            }
+
+            shouldThrow = true;
+            let validException = false;
+            let exception = null;
+            revoke();
+            try {
+                f(a, b);
+            } catch(e) {
+                validException = e === "a";
+                exception = e;
+            }
+            if (!validException)
+                throw new Error("Bad operation: " + exception.toString() + " with iters: " + iters);
+        }
+        runTest(2);
+        runTest(10);
+        runTest(50);
+        runTest(1000);
+        runTest(10000);
+    `;
+    eval(test);
+}
+let ops = [
+    "+"
+    , "-"
+    , "*"
+    , "**"
+    , "/"
+    , "%"
+    , "&"
+    , "|"
+    , "^"
+    , ">>"
+    , ">>>"
+    , "<<"
+];
+for (let op of ops)
+    test(op);
+
+function test2(op) {
+    function runTest(iters) {
+        let test = `
+            let shouldThrow = false;
+            let a = {
+                valueOf() { 
+                    if (shouldThrow)
+                        throw "a";
+                    return 0;
+                }
+            };
+            let {proxy: b, revoke} = Proxy.revocable({}, {
+                get: function(target, prop) {
+                    if (prop === "valueOf") {
+                        if (shouldThrow)
+                            throw new Error("Should not be here!");
+                        return function() {
+                            return 0;
+                        }
+                    }
+                }
+            });
+            function f(a, b) {
+                return a ${op} b;
+            }
+            noInline(f);
+            for (let i = 0; i < ${iters}; i++) {
+                f(a, b);
+            }
+
+            shouldThrow = true;
+            let validException = false;
+            let exception = null;
+            revoke();
+            try {
+                f(a, b);
+            } catch(e) {
+                validException = e === "a";
+                exception = e;
+            }
+            if (!validException)
+                throw new Error("Bad operation: " + exception.toString() + " with iters: " + ${iters});
+        `;
+        eval(Math.random() + ";" + test);
+    }
+    runTest(2);
+    runTest(10);
+    runTest(50);
+    runTest(1000);
+    runTest(10000);
+}
+for (let op of ops)
+    test2(op);

Modified: trunk/Source/_javascript_Core/ChangeLog (204205 => 204206)


--- trunk/Source/_javascript_Core/ChangeLog	2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-08-06 00:46:50 UTC (rev 204206)
@@ -1,3 +1,33 @@
+2016-08-05  Saam Barati  <sbar...@apple.com>
+
+        various math operations don't properly check for an exception after calling toNumber() on the lhs
+        https://bugs.webkit.org/show_bug.cgi?id=160154
+
+        Reviewed by Mark Lam.
+
+        We must check for an exception after calling toNumber() on the lhs
+        because this can throw an exception. If we called toNumber() on
+        the rhs without first checking for an exception after the toNumber()
+        on the lhs, this can lead us to execute effectful code or deviate
+        from the standard in subtle ways. I fixed this bug in various places
+        by always checking for an exception after calling toNumber() on the
+        lhs for the various bit and arithmetic operations.
+
+        This patch also found a commutativity bug inside DFGStrengthReduction.
+        We could end up commuting the lhs and rhs of say an "|" _expression_
+        even when the lhs/rhs may not be numbers. This is wrong because
+        executing toNumber() on the lhs/rhs has strict ordering guarantees
+        by the specification and is observable by user programs.
+
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleCommutativity):
+        * jit/JITOperations.cpp:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/Operations.cpp:
+        (JSC::jsAddSlowCase):
+
 2016-08-05  Michael Saboff  <msab...@apple.com>
 
         compilePutByValForIntTypedArray() has a slow path in the middle of its processing

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (204205 => 204206)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-08-06 00:46:50 UTC (rev 204206)
@@ -210,6 +210,8 @@
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
     int32_t b = op2.toInt32(exec);
     return JSValue::encode(jsNumber(a & b));
 }
@@ -223,6 +225,8 @@
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
     int32_t b = op2.toInt32(exec);
     return JSValue::encode(jsNumber(a | b));
 }
@@ -236,6 +240,8 @@
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
     int32_t b = op2.toInt32(exec);
     return JSValue::encode(jsNumber(a ^ b));
 }
@@ -249,6 +255,8 @@
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
     uint32_t b = op2.toUInt32(exec);
     return JSValue::encode(jsNumber(a << (b & 0x1f)));
 }
@@ -262,6 +270,8 @@
     JSValue op2 = JSValue::decode(encodedOp2);
 
     int32_t a = op1.toInt32(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
     uint32_t b = op2.toUInt32(exec);
     return JSValue::encode(jsNumber(a >> (b & 0x1f)));
 }
@@ -275,6 +285,8 @@
     JSValue op2 = JSValue::decode(encodedOp2);
 
     uint32_t a = op1.toUInt32(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
     uint32_t b = op2.toUInt32(exec);
     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
 }
@@ -304,6 +316,8 @@
     JSValue op2 = JSValue::decode(encodedOp2);
 
     double a = op1.toNumber(exec);
+    if (UNLIKELY(vm->exception()))
+        return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a / b));
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (204205 => 204206)


--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2016-08-06 00:46:50 UTC (rev 204206)
@@ -744,6 +744,11 @@
     
     void handleCommutativity()
     {
+        // It's definitely not sound to swap the lhs and rhs when we may be performing effectful
+        // calls on the lhs/rhs for valueOf.
+        if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse)
+            return;
+
         // If the right side is a constant then there is nothing left to do.
         if (m_node->child2()->hasConstant())
             return;
@@ -750,7 +755,7 @@
         
         // This case ensures that optimizations that look for x + const don't also have
         // to look for const + x.
-        if (m_node->child1()->hasConstant()) {
+        if (m_node->child1()->hasConstant() && !m_node->child1()->asJSValue().isCell()) {
             std::swap(m_node->child1(), m_node->child2());
             m_changed = true;
             return;

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (204205 => 204206)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2016-08-06 00:46:50 UTC (rev 204206)
@@ -2354,17 +2354,19 @@
     return JSValue::encode(result);
 }
 
-ALWAYS_INLINE static EncodedJSValue unprofiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+ALWAYS_INLINE static EncodedJSValue unprofiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     double a = op1.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a * b));
 }
 
-ALWAYS_INLINE static EncodedJSValue profiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
+ALWAYS_INLINE static EncodedJSValue profiledMul(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
 {
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
@@ -2373,7 +2375,11 @@
         arithProfile->observeLHSAndRHS(op1, op2);
 
     double a = op1.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
     
     JSValue result = jsNumber(a * b);
     arithProfile->observeResult(result);
@@ -2385,7 +2391,7 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    return unprofiledMul(exec, encodedOp1, encodedOp2);
+    return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
 }
 
 EncodedJSValue JIT_OPERATION operationValueMulNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*)
@@ -2393,7 +2399,7 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    return unprofiledMul(exec, encodedOp1, encodedOp2);
+    return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
 }
 
 EncodedJSValue JIT_OPERATION operationValueMulOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC)
@@ -2410,7 +2416,7 @@
     exec->codeBlock()->dumpMathICStats();
 #endif
 
-    return unprofiledMul(exec, encodedOp1, encodedOp2);
+    return unprofiledMul(*vm, exec, encodedOp1, encodedOp2);
 }
 
 EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
@@ -2418,7 +2424,7 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile);
+    return profiledMul(*vm, exec, encodedOp1, encodedOp2, arithProfile);
 }
 
 EncodedJSValue JIT_OPERATION operationValueMulProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITMulIC* mulIC)
@@ -2434,7 +2440,7 @@
     exec->codeBlock()->dumpMathICStats();
 #endif
 
-    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile, false);
+    return profiledMul(*vm, exec, encodedOp1, encodedOp2, arithProfile, false);
 }
 
 EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITMulIC*)
@@ -2442,20 +2448,22 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile);
+    return profiledMul(*vm, exec, encodedOp1, encodedOp2, arithProfile);
 }
 
-ALWAYS_INLINE static EncodedJSValue unprofiledSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+ALWAYS_INLINE static EncodedJSValue unprofiledSub(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
 
     double a = op1.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a - b));
 }
 
-ALWAYS_INLINE static EncodedJSValue profiledSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
+ALWAYS_INLINE static EncodedJSValue profiledSub(VM& vm, ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
 {
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
@@ -2464,7 +2472,11 @@
         arithProfile->observeLHSAndRHS(op1, op2);
 
     double a = op1.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
     double b = op2.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        return JSValue::encode(JSValue());
     
     JSValue result = jsNumber(a - b);
     arithProfile->observeResult(result);
@@ -2475,7 +2487,7 @@
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
-    return unprofiledSub(exec, encodedOp1, encodedOp2);
+    return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
 }
 
 EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
@@ -2483,7 +2495,7 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    return profiledSub(exec, encodedOp1, encodedOp2, arithProfile);
+    return profiledSub(*vm, exec, encodedOp1, encodedOp2, arithProfile);
 }
 
 EncodedJSValue JIT_OPERATION operationValueSubOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC)
@@ -2500,7 +2512,7 @@
     exec->codeBlock()->dumpMathICStats();
 #endif
 
-    return unprofiledSub(exec, encodedOp1, encodedOp2);
+    return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
 }
 
 EncodedJSValue JIT_OPERATION operationValueSubNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC*)
@@ -2508,7 +2520,7 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    return unprofiledSub(exec, encodedOp1, encodedOp2);
+    return unprofiledSub(*vm, exec, encodedOp1, encodedOp2);
 }
 
 EncodedJSValue JIT_OPERATION operationValueSubProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITSubIC* subIC)
@@ -2524,7 +2536,7 @@
     exec->codeBlock()->dumpMathICStats();
 #endif
 
-    return profiledSub(exec, encodedOp1, encodedOp2, arithProfile, false);
+    return profiledSub(*vm, exec, encodedOp1, encodedOp2, arithProfile, false);
 }
 
 EncodedJSValue JIT_OPERATION operationValueSubProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITSubIC*)
@@ -2532,7 +2544,7 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    return profiledSub(exec, encodedOp1, encodedOp2, arithProfile);
+    return profiledSub(*vm, exec, encodedOp1, encodedOp2, arithProfile);
 }
 
 void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec)

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (204205 => 204206)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2016-08-06 00:46:50 UTC (rev 204206)
@@ -434,6 +434,8 @@
     JSValue left = OP_C(2).jsValue();
     JSValue right = OP_C(3).jsValue();
     double a = left.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     double b = right.toNumber(exec);
     JSValue result = jsNumber(a * b);
     RETURN_WITH_PROFILING(result, {
@@ -447,6 +449,8 @@
     JSValue left = OP_C(2).jsValue();
     JSValue right = OP_C(3).jsValue();
     double a = left.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     double b = right.toNumber(exec);
     JSValue result = jsNumber(a - b);
     RETURN_WITH_PROFILING(result, {
@@ -460,7 +464,11 @@
     JSValue left = OP_C(2).jsValue();
     JSValue right = OP_C(3).jsValue();
     double a = left.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     double b = right.toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     JSValue result = jsNumber(a / b);
     RETURN_WITH_PROFILING(result, {
         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
@@ -471,6 +479,8 @@
 {
     BEGIN();
     double a = OP_C(2).jsValue().toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     double b = OP_C(3).jsValue().toNumber(exec);
     RETURN(jsNumber(jsMod(a, b)));
 }
@@ -479,7 +489,11 @@
 {
     BEGIN();
     double a = OP_C(2).jsValue().toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     double b = OP_C(3).jsValue().toNumber(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     RETURN(jsNumber(operationMathPow(a, b)));
 }
 
@@ -487,6 +501,8 @@
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
     RETURN(jsNumber(a << (b & 31)));
 }
@@ -495,6 +511,8 @@
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
     RETURN(jsNumber(a >> (b & 31)));
 }
@@ -503,6 +521,8 @@
 {
     BEGIN();
     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
 }
@@ -518,6 +538,8 @@
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     int32_t b = OP_C(3).jsValue().toInt32(exec);
     RETURN(jsNumber(a & b));
 }
@@ -526,6 +548,8 @@
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     int32_t b = OP_C(3).jsValue().toInt32(exec);
     RETURN(jsNumber(a | b));
 }
@@ -534,6 +558,8 @@
 {
     BEGIN();
     int32_t a = OP_C(2).jsValue().toInt32(exec);
+    if (UNLIKELY(vm.exception()))
+        RETURN(JSValue());
     int32_t b = OP_C(3).jsValue().toInt32(exec);
     RETURN(jsNumber(a ^ b));
 }

Modified: trunk/Source/_javascript_Core/runtime/Operations.cpp (204205 => 204206)


--- trunk/Source/_javascript_Core/runtime/Operations.cpp	2016-08-06 00:32:03 UTC (rev 204205)
+++ trunk/Source/_javascript_Core/runtime/Operations.cpp	2016-08-06 00:46:50 UTC (rev 204206)
@@ -43,8 +43,13 @@
 NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
 {
     // exception for the Date exception in defaultValue()
+    VM& vm = callFrame->vm();
     JSValue p1 = v1.toPrimitive(callFrame);
+    if (UNLIKELY(vm.exception()))
+        return JSValue();
     JSValue p2 = v2.toPrimitive(callFrame);
+    if (UNLIKELY(vm.exception()))
+        return JSValue();
 
     if (p1.isString())
         return jsString(callFrame, asString(p1), p2.toString(callFrame));
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to