Title: [217062] trunk
Revision
217062
Author
[email protected]
Date
2017-05-18 12:55:01 -0700 (Thu, 18 May 2017)

Log Message

Constructor calls set this too early
https://bugs.webkit.org/show_bug.cgi?id=172302

Reviewed by Saam Barati.
        
JSTests:

This tests all three kinds of constructs in BytecodeGenerator. All three were previously
wrong.

* stress/construct-overwritten-variable.js: Added.
(new.x.x):
* stress/construct-spread-overwritten-variable-2.js: Added.
(new.x.x):
* stress/construct-spread-overwritten-variable.js: Added.
(new.x.x):

Source/_javascript_Core:

We were setting this before evaluating the arguments, so this code:
        
    var x = 42;
    new x(x = function() { });
        
Would crash because we would pass 42 as this, and create_this would treat it as a cell.
Dereferencing a non-cell is guaranteed to crash.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitConstruct):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::NewExprNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (217061 => 217062)


--- trunk/JSTests/ChangeLog	2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/JSTests/ChangeLog	2017-05-18 19:55:01 UTC (rev 217062)
@@ -1,3 +1,20 @@
+2017-05-18  Filip Pizlo  <[email protected]>
+
+        Constructor calls set this too early
+        https://bugs.webkit.org/show_bug.cgi?id=172302
+
+        Reviewed by Saam Barati.
+        
+        This tests all three kinds of constructs in BytecodeGenerator. All three were previously
+        wrong.
+
+        * stress/construct-overwritten-variable.js: Added.
+        (new.x.x):
+        * stress/construct-spread-overwritten-variable-2.js: Added.
+        (new.x.x):
+        * stress/construct-spread-overwritten-variable.js: Added.
+        (new.x.x):
+
 2017-05-18  Saam Barati  <[email protected]>
 
         WebAssembly: perform stack checks

Added: trunk/JSTests/stress/construct-overwritten-variable.js (0 => 217062)


--- trunk/JSTests/stress/construct-overwritten-variable.js	                        (rev 0)
+++ trunk/JSTests/stress/construct-overwritten-variable.js	2017-05-18 19:55:01 UTC (rev 217062)
@@ -0,0 +1,6 @@
+//@ runDefault
+
+(function(){
+    var x = 42;
+    new x(x = function(){ });
+})();

Added: trunk/JSTests/stress/construct-spread-overwritten-variable-2.js (0 => 217062)


--- trunk/JSTests/stress/construct-spread-overwritten-variable-2.js	                        (rev 0)
+++ trunk/JSTests/stress/construct-spread-overwritten-variable-2.js	2017-05-18 19:55:01 UTC (rev 217062)
@@ -0,0 +1,6 @@
+//@ runDefault
+
+(function(){
+    var x = 42;
+    new x(...[x = function(){ }]);
+})();

Added: trunk/JSTests/stress/construct-spread-overwritten-variable.js (0 => 217062)


--- trunk/JSTests/stress/construct-spread-overwritten-variable.js	                        (rev 0)
+++ trunk/JSTests/stress/construct-spread-overwritten-variable.js	2017-05-18 19:55:01 UTC (rev 217062)
@@ -0,0 +1,7 @@
+//@ runDefault
+
+(function(){
+    var x = 42;
+    var a = [1, 2, 3];
+    new x(x = function(){ }, ...a);
+})();

Modified: trunk/Source/_javascript_Core/ChangeLog (217061 => 217062)


--- trunk/Source/_javascript_Core/ChangeLog	2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-05-18 19:55:01 UTC (rev 217062)
@@ -1,3 +1,25 @@
+2017-05-18  Filip Pizlo  <[email protected]>
+
+        Constructor calls set this too early
+        https://bugs.webkit.org/show_bug.cgi?id=172302
+
+        Reviewed by Saam Barati.
+        
+        We were setting this before evaluating the arguments, so this code:
+        
+            var x = 42;
+            new x(x = function() { });
+        
+        Would crash because we would pass 42 as this, and create_this would treat it as a cell.
+        Dereferencing a non-cell is guaranteed to crash.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitConstruct):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::NewExprNode::emitBytecode):
+        (JSC::FunctionCallValueNode::emitBytecode):
+
 2017-05-18  Saam Barati  <[email protected]>
 
         WebAssembly: perform stack checks

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (217061 => 217062)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2017-05-18 19:55:01 UTC (rev 217062)
@@ -3638,7 +3638,7 @@
     return src;
 }
 
-RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
+RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, RegisterID* lazyThis, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
 {
     ASSERT(func->refCount());
 
@@ -3659,6 +3659,7 @@
                     instructions().append(argumentRegister.get()->index());
                     instructions().append(argumentRegister.get()->index());
 
+                    emitMove(callArguments.thisRegister(), lazyThis);
                     RefPtr<RegisterID> thisRegister = emitMove(newTemporary(), callArguments.thisRegister());
                     return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
                 }
@@ -3665,6 +3666,7 @@
             }
             RefPtr<RegisterID> argumentRegister;
             argumentRegister = _expression_->emitBytecode(*this, callArguments.argumentRegister(0));
+            emitMove(callArguments.thisRegister(), lazyThis);
             return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
         }
         
@@ -3671,7 +3673,9 @@
         for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
             emitNode(callArguments.argumentRegister(argument++), n);
     }
-
+    
+    emitMove(callArguments.thisRegister(), lazyThis);
+    
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, CallFrame::headerSizeInRegisters, UnsafeVectorOverflow> callFrame;
     for (int i = 0; i < CallFrame::headerSizeInRegisters; ++i)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (217061 => 217062)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2017-05-18 19:55:01 UTC (rev 217062)
@@ -683,7 +683,7 @@
         RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal);
         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
 
-        RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
+        RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, RegisterID* lazyThis, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
         RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
         void emitToPrimitive(RegisterID* dst, RegisterID* src);
 

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (217061 => 217062)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2017-05-18 19:40:48 UTC (rev 217061)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2017-05-18 19:55:01 UTC (rev 217062)
@@ -733,8 +733,7 @@
     RefPtr<RegisterID> func = generator.emitNode(m_expr);
     RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
     CallArguments callArguments(generator, m_args);
-    generator.emitMove(callArguments.thisRegister(), func.get());
-    return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
+    return generator.emitConstruct(returnValue.get(), func.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
 }
 
 CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
@@ -816,8 +815,7 @@
 
         ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
         ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
-        generator.emitMove(callArguments.thisRegister(), generator.newTarget());
-        RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+        RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), generator.newTarget(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
 
         bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
         bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to