Suppress ASAN on valid stack accesses in Probe-based OSRExit::executeOSRExit().
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Dec 2018 22:46:50 +0000 (22:46 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Dec 2018 22:46:50 +0000 (22:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192776
<rdar://problem/46772368>

Reviewed by Keith Miller.

JSTests:

* stress/out-of-frame-stack-accesses-due-to-probe-based-osr-exits.js: Added.

Source/JavaScriptCore:

1. Add some asanUnsafe methods to the Register class.
2. Update the probe-based OSRExit::executeOSRExit() to use these asanUnsafe methods.

* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::executeOSRExit):
* interpreter/Register.h:
(JSC::Register::asanUnsafeUnboxedInt32 const):
(JSC::Register::asanUnsafeUnboxedInt52 const):
(JSC::Register::asanUnsafeUnboxedStrictInt52 const):
(JSC::Register::asanUnsafeUnboxedDouble const):
(JSC::Register::asanUnsafeUnboxedCell const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239290 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/out-of-frame-stack-accesses-due-to-probe-based-osr-exits.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGOSRExit.cpp
Source/JavaScriptCore/interpreter/Register.h

index 6fa0a87..ed27c76 100644 (file)
@@ -1,5 +1,15 @@
 2018-12-17  Mark Lam  <mark.lam@apple.com>
 
+        Suppress ASAN on valid stack accesses in Probe-based OSRExit::executeOSRExit().
+        https://bugs.webkit.org/show_bug.cgi?id=192776
+        <rdar://problem/46772368>
+
+        Reviewed by Keith Miller.
+
+        * stress/out-of-frame-stack-accesses-due-to-probe-based-osr-exits.js: Added.
+
+2018-12-17  Mark Lam  <mark.lam@apple.com>
+
         Fix stale assertion in attemptToForceStringArrayModeByToStringConversion().
         https://bugs.webkit.org/show_bug.cgi?id=192770
         <rdar://problem/46449037>
diff --git a/JSTests/stress/out-of-frame-stack-accesses-due-to-probe-based-osr-exits.js b/JSTests/stress/out-of-frame-stack-accesses-due-to-probe-based-osr-exits.js
new file mode 100644 (file)
index 0000000..99bb5cc
--- /dev/null
@@ -0,0 +1,14 @@
+//@ requireOptions("--useProbeOSRExit=true", ""--forceEagerCompilation=true"")
+
+// This test passes if it does not crash especially on ASAN builds.
+
+let x = 0;
+function Foo(a) {
+    a === a;
+    '' + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x;
+}
+
+for (let i=0; i<8; i++)
+    new Foo(0);
+
+new Foo({});
index 2d41d86..715d0ad 100644 (file)
@@ -1,5 +1,25 @@
 2018-12-17  Mark Lam  <mark.lam@apple.com>
 
+        Suppress ASAN on valid stack accesses in Probe-based OSRExit::executeOSRExit().
+        https://bugs.webkit.org/show_bug.cgi?id=192776
+        <rdar://problem/46772368>
+
+        Reviewed by Keith Miller.
+
+        1. Add some asanUnsafe methods to the Register class.
+        2. Update the probe-based OSRExit::executeOSRExit() to use these asanUnsafe methods.
+
+        * dfg/DFGOSRExit.cpp:
+        (JSC::DFG::OSRExit::executeOSRExit):
+        * interpreter/Register.h:
+        (JSC::Register::asanUnsafeUnboxedInt32 const):
+        (JSC::Register::asanUnsafeUnboxedInt52 const):
+        (JSC::Register::asanUnsafeUnboxedStrictInt52 const):
+        (JSC::Register::asanUnsafeUnboxedDouble const):
+        (JSC::Register::asanUnsafeUnboxedCell const):
+
+2018-12-17  Mark Lam  <mark.lam@apple.com>
+
         Fix stale assertion in attemptToForceStringArrayModeByToStringConversion().
         https://bugs.webkit.org/show_bug.cgi?id=192770
         <rdar://problem/46449037>
index 6ea9776..069cf85 100644 (file)
@@ -569,7 +569,7 @@ void OSRExit::executeOSRExit(Context& context)
 
         switch (recovery.technique()) {
         case DisplacedInJSStack:
-            frame.setOperand(operand, exec->r(recovery.virtualRegister()).jsValue());
+            frame.setOperand(operand, exec->r(recovery.virtualRegister()).asanUnsafeJSValue());
             break;
 
         case InFPR:
@@ -591,7 +591,7 @@ void OSRExit::executeOSRExit(Context& context)
             break;
 
         case CellDisplacedInJSStack:
-            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).unboxedCell()));
+            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).asanUnsafeUnboxedCell()));
             break;
 
 #if USE(JSVALUE32_64)
@@ -602,9 +602,9 @@ void OSRExit::executeOSRExit(Context& context)
 
         case BooleanDisplacedInJSStack:
 #if USE(JSVALUE64)
-            frame.setOperand(operand, exec->r(recovery.virtualRegister()).jsValue());
+            frame.setOperand(operand, exec->r(recovery.virtualRegister()).asanUnsafeJSValue());
 #else
-            frame.setOperand(operand, jsBoolean(exec->r(recovery.virtualRegister()).jsValue().payload()));
+            frame.setOperand(operand, jsBoolean(exec->r(recovery.virtualRegister()).asanUnsafeJSValue().payload()));
 #endif
             break;
 
@@ -613,7 +613,7 @@ void OSRExit::executeOSRExit(Context& context)
             break;
 
         case Int32DisplacedInJSStack:
-            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).unboxedInt32()));
+            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).asanUnsafeUnboxedInt32()));
             break;
 
 #if USE(JSVALUE64)
@@ -622,7 +622,7 @@ void OSRExit::executeOSRExit(Context& context)
             break;
 
         case Int52DisplacedInJSStack:
-            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).unboxedInt52()));
+            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).asanUnsafeUnboxedInt52()));
             break;
 
         case UnboxedStrictInt52InGPR:
@@ -630,7 +630,7 @@ void OSRExit::executeOSRExit(Context& context)
             break;
 
         case StrictInt52DisplacedInJSStack:
-            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).unboxedStrictInt52()));
+            frame.setOperand(operand, JSValue(exec->r(recovery.virtualRegister()).asanUnsafeUnboxedStrictInt52()));
             break;
 #endif
 
@@ -639,7 +639,7 @@ void OSRExit::executeOSRExit(Context& context)
             break;
 
         case DoubleDisplacedInJSStack:
-            frame.setOperand(operand, JSValue(JSValue::EncodeAsDouble, purifyNaN(exec->r(recovery.virtualRegister()).unboxedDouble())));
+            frame.setOperand(operand, JSValue(JSValue::EncodeAsDouble, purifyNaN(exec->r(recovery.virtualRegister()).asanUnsafeUnboxedDouble())));
             break;
 
         case Constant:
index 8bc686f..60389b4 100644 (file)
@@ -65,11 +65,16 @@ namespace JSC {
         JSObject* object() const;
         JSScope* scope() const;
         int32_t unboxedInt32() const;
+        int32_t asanUnsafeUnboxedInt32() const;
         int64_t unboxedInt52() const;
+        int64_t asanUnsafeUnboxedInt52() const;
         int64_t unboxedStrictInt52() const;
+        int64_t asanUnsafeUnboxedStrictInt52() const;
         bool unboxedBoolean() const;
         double unboxedDouble() const;
+        double asanUnsafeUnboxedDouble() const;
         JSCell* unboxedCell() const;
+        JSCell* asanUnsafeUnboxedCell() const;
         int32_t payload() const;
         int32_t tag() const;
         int32_t unsafePayload() const;
@@ -170,16 +175,31 @@ namespace JSC {
         return payload();
     }
 
+    SUPPRESS_ASAN ALWAYS_INLINE int32_t Register::asanUnsafeUnboxedInt32() const
+    {
+        return unsafePayload();
+    }
+
     ALWAYS_INLINE int64_t Register::unboxedInt52() const
     {
         return u.integer >> JSValue::int52ShiftAmount;
     }
 
+    SUPPRESS_ASAN ALWAYS_INLINE int64_t Register::asanUnsafeUnboxedInt52() const
+    {
+        return u.integer >> JSValue::int52ShiftAmount;
+    }
+
     ALWAYS_INLINE int64_t Register::unboxedStrictInt52() const
     {
         return u.integer;
     }
 
+    SUPPRESS_ASAN ALWAYS_INLINE int64_t Register::asanUnsafeUnboxedStrictInt52() const
+    {
+        return u.integer;
+    }
+
     ALWAYS_INLINE bool Register::unboxedBoolean() const
     {
         return !!payload();
@@ -190,6 +210,11 @@ namespace JSC {
         return u.number;
     }
 
+    SUPPRESS_ASAN ALWAYS_INLINE double Register::asanUnsafeUnboxedDouble() const
+    {
+        return u.number;
+    }
+
     ALWAYS_INLINE JSCell* Register::unboxedCell() const
     {
 #if USE(JSVALUE64)
@@ -199,6 +224,15 @@ namespace JSC {
 #endif
     }
 
+    SUPPRESS_ASAN ALWAYS_INLINE JSCell* Register::asanUnsafeUnboxedCell() const
+    {
+#if USE(JSVALUE64)
+        return u.encodedValue.ptr;
+#else
+        return bitwise_cast<JSCell*>(payload());
+#endif
+    }
+
     ALWAYS_INLINE void* Register::pointer() const
     {
 #if USE(JSVALUE64)