<rdar://problem/6469742> Crash in JSC::TypeInfo::hasStandardGetOwnPropertySlot() running jsfunfuzz
Reviewed by Darin Adler
The problem that caused this was that with nodes were not correctly protecting
the final object that was placed in the scope chain. We correct this by forcing
the use of a temporary register (which stops us relying on a local register
protecting the scope) and changing the behaviour of op_push_scope so that it
will store the final scope object.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@39524
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2008-12-30 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ <https://bugs.webkit.org/show_bug.cgi?id=23049> [jsfunfuzz] With blocks do not correctly protect their scope object
+ <rdar://problem/6469742> Crash in JSC::TypeInfo::hasStandardGetOwnPropertySlot() running jsfunfuzz
+
+ The problem that caused this was that with nodes were not correctly protecting
+ the final object that was placed in the scope chain. We correct this by forcing
+ the use of a temporary register (which stops us relying on a local register
+ protecting the scope) and changing the behaviour of op_push_scope so that it
+ will store the final scope object.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitPushScope):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ (JSC::Interpreter::cti_op_push_scope):
+ * interpreter/Interpreter.h:
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * parser/Nodes.cpp:
+ (JSC::WithNode::emitBytecode):
+
2008-12-30 Cameron Zwarich <cwzwarich@uwaterloo.ca>
Reviewed by Sam Weinig.
RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
{
+ ASSERT(scope->isTemporary());
ControlFlowContext context;
context.isFinallyBlock = false;
m_scopeContextStack.append(context);
/* push_scope scope(r)
Converts register scope to object, and pushes it onto the top
- of the current scope chain.
+ of the current scope chain. The contents of the register scope
+ are replaced by the result of toObject conversion of the scope.
*/
int scope = (++vPC)->u.operand;
JSValue* v = callFrame[scope].jsValue(callFrame);
JSObject* o = v->toObject(callFrame);
CHECK_FOR_EXCEPTION();
+ callFrame[scope] = o;
callFrame->setScopeChain(callFrame->scopeChain()->push(o));
++vPC;
return temp;
}
-void Interpreter::cti_op_push_scope(STUB_ARGS)
+JSObject* Interpreter::cti_op_push_scope(STUB_ARGS)
{
BEGIN_STUB_FUNCTION();
JSObject* o = ARG_src1->toObject(ARG_callFrame);
- CHECK_FOR_EXCEPTION_VOID();
+ CHECK_FOR_EXCEPTION();
ARG_callFrame->setScopeChain(ARG_callFrame->scopeChain()->push(o));
+ return o;
}
void Interpreter::cti_op_pop_scope(STUB_ARGS)
static JSValue* JIT_STUB cti_op_throw(STUB_ARGS);
static JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS);
static JSValue* JIT_STUB cti_op_next_pname(STUB_ARGS);
- static void JIT_STUB cti_op_push_scope(STUB_ARGS);
+ static JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS);
static void JIT_STUB cti_op_pop_scope(STUB_ARGS);
static JSValue* JIT_STUB cti_op_typeof(STUB_ARGS);
static JSValue* JIT_STUB cti_op_is_undefined(STUB_ARGS);
case op_push_scope: {
emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
emitCTICall(Interpreter::cti_op_push_scope);
+ emitPutVirtualRegister(currentInstruction[1].u.operand);
NEXT_OPCODE(op_push_scope);
}
case op_pop_scope: {
RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
+ RefPtr<RegisterID> scope = generator.newTemporary();
+ generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped
generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
generator.emitPushScope(scope.get());
RegisterID* result = generator.emitNode(dst, m_statement.get());
+2008-12-30 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ <https://bugs.webkit.org/show_bug.cgi?id=23049> [jsfunfuzz] With blocks do not correctly protect their scope object
+ <rdar://problem/6469742> Crash in JSC::TypeInfo::hasStandardGetOwnPropertySlot() running jsfunfuzz
+
+ Tests to ensure we correctly protect the scope object from GC.
+
+ * fast/js/resources/with-scope-gc.js: Added.
+ * fast/js/with-scope-gc-expected.txt: Added.
+ * fast/js/with-scope-gc.html: Added.
+
2008-12-30 Simon Fraser <simon.fraser@apple.com>
Fix spurious test failures by rounding floating point values to
--- /dev/null
+description(
+'Tests to make sure that dynamic scope objects are correctly protected from GC. To pass we need to not crash.'
+);
+
+function gc()
+{
+ if (this.GCController)
+ GCController.collect();
+ else
+ for (var i = 0; i < 10000; ++i) // Allocate a sufficient number of objects to force a GC.
+ ({});
+}
+
+(function() {
+ try {
+ // Immediate value for scope
+ with(1) { gc(); a; }
+ } catch(e) {
+ }
+})();
+
+(function() {
+ try {
+ // Real object for scope
+ var local;
+ with (local = {}) {
+ z=null;
+ {}; {}; [1,2,3,4*{}]; // Clobber any temporaries the scope may exist in
+ gc();
+ b;
+ }
+ } catch (e) {
+ }
+})();
+
+(function() {
+ try {
+ // Test catch blocks for the heck of it
+ try {
+ throw 1;
+ } catch(e) {
+ gc();
+ b;
+ }
+ } catch (e) {
+ }
+})();
+
+var successfullyParsed = true;
--- /dev/null
+Tests to make sure that dynamic scope objects are correctly protected from GC. To pass we need to not crash.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/with-scope-gc.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>