diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2009-11-23 14:26:36 (GMT) |
---|---|---|
committer | Jason McDonald <jason.mcdonald@nokia.com> | 2009-11-24 03:19:30 (GMT) |
commit | c27e9337b127d8946844f448892de0da31bbe8f3 (patch) | |
tree | 0a2bb0581a3b0f042e88ab50d92512d3c0b115d4 | |
parent | 30c51abc4eefa9ccf4311d07100fe383df62bf32 (diff) | |
download | Qt-c27e9337b127d8946844f448892de0da31bbe8f3.zip Qt-c27e9337b127d8946844f448892de0da31bbe8f3.tar.gz Qt-c27e9337b127d8946844f448892de0da31bbe8f3.tar.bz2 |
Don't crash in eval() function when QtScript debugger is attached
The built-in eval() function bypasses the script registration
performed by QScriptEngine::evaluate(), so if we get an
atStatement() callback from JSC from that script, the
scriptID-to-sourceProvider lookup will fail.
In this case, just return from atStatement() without delivering
the positionChange() callback to the QScriptEngineAgent, since
the agent will not have received the scriptLoad() callback for
that script anyway.
This is a change in behavior from 4.5, but we consider it
the minimum-impact fix at this point to keep 4.6.0 from
crashing. The only downside is that debugging will
effectively be "disabled" for the script passed to eval(),
but that's a lot better than crashing.
Task-number: QTBUG-6108
Reviewed-by: Jedrzej Nowacki
(cherry picked from commit 23002374d11598b26b6585e78dc073071a13f0ec)
-rw-r--r-- | src/script/api/qscriptengineagent.cpp | 10 | ||||
-rw-r--r-- | tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp | 28 |
2 files changed, 36 insertions, 2 deletions
diff --git a/src/script/api/qscriptengineagent.cpp b/src/script/api/qscriptengineagent.cpp index e7998b7..a2af514 100644 --- a/src/script/api/qscriptengineagent.cpp +++ b/src/script/api/qscriptengineagent.cpp @@ -154,7 +154,10 @@ void QScriptEngineAgentPrivate::exceptionCatch(const JSC::DebuggerCallFrame& fra void QScriptEngineAgentPrivate::atStatement(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, int column) { QScript::UStringSourceProviderWithFeedback *source = engine->loadedScripts.value(sourceID); - Q_ASSERT(source != 0); + if (!source) { + // QTBUG-6108: We don't have the source for this script, so ignore. + return; + } column = source->columnNumberFromOffset(column); JSC::CallFrame *oldFrame = engine->currentFrame; int oldAgentLineNumber = engine->agentLineNumber; @@ -183,7 +186,10 @@ void QScriptEngineAgentPrivate::didReachBreakpoint(const JSC::DebuggerCallFrame& { if (q_ptr->supportsExtension(QScriptEngineAgent::DebuggerInvocationRequest)) { QScript::UStringSourceProviderWithFeedback *source = engine->loadedScripts.value(sourceID); - Q_ASSERT(source != 0); + if (!source) { + // QTBUG-6108: We don't have the source for this script, so ignore. + return; + } column = source->columnNumberFromOffset(column); JSC::CallFrame *oldFrame = engine->currentFrame; int oldAgentLineNumber = engine->agentLineNumber; diff --git a/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp b/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp index ac018cd..840eb16 100644 --- a/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp +++ b/tests/auto/qscriptengineagent/tst_qscriptengineagent.cpp @@ -114,6 +114,7 @@ private slots: void evaluateProgram(); void evaluateProgram_SyntaxError(); void evaluateNullProgram(); + void QTBUG6108(); private: double m_testProperty; @@ -2306,5 +2307,32 @@ void tst_QScriptEngineAgent::evaluateNullProgram() QCOMPARE(spy->count(), 0); } +void tst_QScriptEngineAgent::QTBUG6108() +{ + QScriptEngine eng; + ScriptEngineSpy *spy = new ScriptEngineSpy(&eng); + eng.evaluate("eval('a = 1')"); + QCOMPARE(spy->count(), 5); + + QCOMPARE(spy->at(0).type, ScriptEngineEvent::ScriptLoad); + QVERIFY(spy->at(0).scriptId != -1); + + QCOMPARE(spy->at(1).type, ScriptEngineEvent::FunctionEntry); + QVERIFY(spy->at(1).scriptId != -1); + QCOMPARE(spy->at(1).scriptId, spy->at(0).scriptId); + + QCOMPARE(spy->at(2).type, ScriptEngineEvent::PositionChange); + QVERIFY(spy->at(2).scriptId != -1); + QCOMPARE(spy->at(2).scriptId, spy->at(0).scriptId); + QCOMPARE(spy->at(2).lineNumber, 1); + + QCOMPARE(spy->at(3).type, ScriptEngineEvent::FunctionExit); + QVERIFY(spy->at(3).scriptId != -1); + QCOMPARE(spy->at(3).scriptId, spy->at(0).scriptId); + + QCOMPARE(spy->at(4).type, ScriptEngineEvent::ScriptUnload); + QCOMPARE(spy->at(4).scriptId, spy->at(0).scriptId); +} + QTEST_MAIN(tst_QScriptEngineAgent) #include "tst_qscriptengineagent.moc" |