diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-10-17 15:14:59 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-10-23 06:27:33 +0000 |
commit | bc2427ce32efbfa3759e2658ba53289428527071 (patch) | |
tree | d4b454d585c1f66cb87cec8b3449a084a7c692b2 /src/qml/jsruntime | |
parent | aceb0d0cd2da89aebbf17729869b9e977290c826 (diff) |
Never truncate the JS stack
Truncating it can lead to all sorts of crazy side effects, especially
as we'd be extending it again when leaving the function. When that happens
already freed JS objects could suddenly become visible to the GC again.
Fix this by copying the CallData to set up a new stack frame. This is not yet
ideal, as we're copying too much data, but that can be fixed separately.
Change-Id: I02a39ce479475bae326f9eddfe6654fbcf8e6d35
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 23 |
2 files changed, 19 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 2e97d8074a..97b0c5259f 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1028,6 +1028,7 @@ ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, C ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { + Q_ASSERT(engine->jsStackTop >= callData->args + callData->argc()); if (!callData->thisObject.isObject()) { Q_ASSERT(!callData->thisObject.isEmpty()); if (callData->thisObject.isNullOrUndefined()) { @@ -1058,6 +1059,7 @@ ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, int nameInde ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) { + Q_ASSERT(engine->jsStackTop >= callData->args + callData->argc()); Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index; callData->function = l->getter(l, engine, callData->thisObject); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index f27a7d452c..4abd3582dd 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -509,6 +509,15 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) Value *jsStackTop = engine->jsStackTop; + Q_ASSERT(engine->jsStackTop >= callData->args + callData->argc() - 1); + Value *stack = engine->jsStackTop; + engine->jsStackTop += sizeof(CallData)/sizeof(Value) - 1 + qMax(callData->argc(), int(function->compiledFunction->nRegisters)); + memcpy(stack, callData, sizeof(CallData) - sizeof(Value) + callData->argc()*sizeof(Value)); + // clear out remaining arguments and local registers + callData = reinterpret_cast<CallData *>(stack); + for (Value *v = callData->args + callData->argc(); v < engine->jsStackTop; ++v) + *v = Encode::undefined(); + CppStackFrame frame; frame.parent = engine->currentStackFrame; frame.v4Function = function; @@ -516,12 +525,6 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) frame.jsFrame = callData; engine->currentStackFrame = &frame; - engine->jsStackTop = reinterpret_cast<QV4::Value *>(callData) + function->compiledFunction->nRegisters + 1; - // clear out remaining arguments and local registers - for (Value *v = callData->args + callData->argc(); v < jsStackTop; ++v) - *v = Encode::undefined(); - - QV4::Value *stack = reinterpret_cast<QV4::Value *>(callData); const uchar *exceptionHandler = 0; QV4::Value &accumulator = frame.jsFrame->accumulator; @@ -741,6 +744,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) STORE_IP(); STORE_ACC(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); acc = Runtime::method_callValue(engine, accumulator, cData); CHECK_EXCEPTION; MOTH_END_INSTR(CallValue) @@ -748,6 +752,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) MOTH_BEGIN_INSTR(CallProperty) STORE_IP(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); cData->thisObject = STACK_VALUE(base); acc = Runtime::method_callProperty(engine, name, cData); CHECK_EXCEPTION; @@ -756,6 +761,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) MOTH_BEGIN_INSTR(CallPropertyLookup) STORE_IP(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); cData->thisObject = STACK_VALUE(base); acc = Runtime::method_callPropertyLookup(engine, lookupIndex, cData); CHECK_EXCEPTION; @@ -764,6 +770,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) MOTH_BEGIN_INSTR(CallElement) STORE_IP(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); cData->thisObject = STACK_VALUE(base); acc = Runtime::method_callElement(engine, STACK_VALUE(index), cData); CHECK_EXCEPTION; @@ -772,6 +779,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) MOTH_BEGIN_INSTR(CallName) STORE_IP(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); acc = Runtime::method_callName(engine, name, cData); CHECK_EXCEPTION; MOTH_END_INSTR(CallName) @@ -779,6 +787,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) MOTH_BEGIN_INSTR(CallPossiblyDirectEval) STORE_IP(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); acc = Runtime::method_callPossiblyDirectEval(engine, cData); CHECK_EXCEPTION; MOTH_END_INSTR(CallPossiblyDirectEval) @@ -786,6 +795,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) MOTH_BEGIN_INSTR(CallGlobalLookup) STORE_IP(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); acc = Runtime::method_callGlobalLookup(engine, index, cData); CHECK_EXCEPTION; MOTH_END_INSTR(CallGlobalLookup) @@ -934,6 +944,7 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) MOTH_BEGIN_INSTR(Construct) STORE_IP(); QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData); + Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop); acc = Runtime::method_construct(engine, STACK_VALUE(func), cData); CHECK_EXCEPTION; MOTH_END_INSTR(Construct) |