diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2017-11-08 15:58:25 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2017-11-11 08:30:19 +0000 |
commit | 85fc49612816dcfc81c9dc265b146b0b90b0f184 (patch) | |
tree | 0dad538dfa59da78201219e82c5d60a0bf1866bc | |
parent | 853b4b08d54f70d04d371d707e50760ffecf2f77 (diff) |
Prevent crashes when profiling translation bindings
The m_v4Function member can now be a nullptr, which means we cannot use
it as ID and we cannot retrieve the source location from it.
Change-Id: Ibb49a3e68cf961f9ffe2a83b2a0b83f7d04e149e
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
4 files changed, 39 insertions, 4 deletions
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 88f8e94f25..6dc9859295 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -237,14 +237,19 @@ public: // Add 1 to the ID, to make it different from the IDs the V4 profiler produces. The +1 makes // the pointer point into the middle of the QV4::Function. Thus it still points to valid // memory but we cannot accidentally create a duplicate key from another object. - quintptr locationId(id(function) + 1); + // If there is no function, use a static but valid address: The profiler itself. + quintptr locationId = function ? id(function) + 1 : id(this); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation), Binding, locationId)); RefLocation &location = m_locations[locationId]; - if (!location.isValid()) - location = RefLocation(function); + if (!location.isValid()) { + if (function) + location = RefLocation(function); + else // Make it valid without actually providing a location + location.locationType = Binding; + } } // Have toByteArrays() construct another RangeData event from the same QString later. diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/qstr.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/qstr.qml new file mode 100644 index 0000000000..09dcd34b5c --- /dev/null +++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/qstr.qml @@ -0,0 +1,9 @@ +import QtQml 2.0 + +Timer { + property string stuff: qsTr("foo") + + running: true + interval: 1 + onTriggered: Qt.quit(); +} diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro index 95d743e9ff..a26f48e6c7 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro +++ b/tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro @@ -19,4 +19,5 @@ OTHER_FILES += \ data/TestImage_2x2.png \ data/signalSourceLocation.qml \ data/javascript.qml \ - data/timer.qml + data/timer.qml \ + data/qstr.qml diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 45e4ad1207..4d37f16e41 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -298,6 +298,7 @@ private slots: void signalSourceLocation(); void javascript(); void flushInterval(); + void translationBinding(); }; #define VERIFY(type, position, expected, checks) QVERIFY(verify(type, position, expected, checks)) @@ -705,6 +706,25 @@ void tst_QQmlProfilerService::flushInterval() checkJsHeap(); } +void tst_QQmlProfilerService::translationBinding() +{ + QCOMPARE(connect(true, "qstr.qml"), ConnectSuccess); + + m_client->sendRecordingStatus(true); + + checkTraceReceived(); + checkJsHeap(); + + QQmlProfilerData expected(0, QQmlProfilerDefinitions::RangeStart, + QQmlProfilerDefinitions::Binding); + VERIFY(MessageListQML, 8, expected, + CheckDetailType | CheckMessageType); + + expected.messageType = QQmlProfilerDefinitions::RangeEnd; + VERIFY(MessageListQML, 10, expected, + CheckDetailType | CheckMessageType); +} + QTEST_MAIN(tst_QQmlProfilerService) #include "tst_qqmlprofilerservice.moc" |