diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-01-04 15:30:49 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-01-05 12:44:17 +0000 |
commit | 781caafe1fde71b059c0e3a42bda77ce0d7e4c2a (patch) | |
tree | d26d68d5948b8ee1516520baebad17ef36d2b244 /tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | |
parent | 5f777705b73ad1d4a11c59ad1468621360658820 (diff) |
Fix decoding of bytecode instructions on ARM generated on x86-64
Due to the difference of sign of the char type, byte code is encoded
differently on x86-64 than if it was on ARM and it also is decoded
differently. The problem at hand here was that negative jumps were
encoded as two-byte instructions (opcode and negative offset as byte) on
x86-64 when qmlcachegen is run. At run-time the negative offset was read
into a char type and consequently interpreted as a positive jump,
leading to crashes.
The explicit use of qint8 as signed byte type in encoding/decoding
sensitive parts avoids the decoding issue and should also result in
consistent encoding.
The added auto-test is (among other configurations) run in the CI under
qemu, which means the x86-64 host-built qmlcachegen will generate byte
code and the tst_qmlcachegen ARM binary will run under qemu and
reproduce this scenario.
Task-number: QTBUG-65521
Change-Id: I615628f53475dad38a41095c6e7ffea0c34d58ac
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp')
-rw-r--r-- | tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 7e81df93b9..fb1072e67f 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -45,6 +45,7 @@ private slots: void translationExpressionSupport(); void signalHandlerParameters(); void errorOnArgumentsInSignalHandler(); + void aheadOfTimeCompilation(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -225,6 +226,39 @@ void tst_qmlcachegen::errorOnArgumentsInSignalHandler() QVERIFY2(errorOutput.contains("error: The use of the arguments object in signal handlers is"), errorOutput); } +void tst_qmlcachegen::aheadOfTimeCompilation() +{ + QTemporaryDir tempDir; + QVERIFY(tempDir.isValid()); + + const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) { + QFile f(tempDir.path() + '/' + fileName); + const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); + Q_ASSERT(ok); + f.write(contents); + return f.fileName(); + }; + + const QString testFilePath = writeTempFile("test.qml", "import QtQml 2.0\n" + "QtObject {\n" + " function runTest() { var x = 0; while (x < 42) { ++x }; return x; }\n" + "}"); + + QVERIFY(generateCache(testFilePath)); + + const QString cacheFilePath = testFilePath + QLatin1Char('c'); + QVERIFY(QFile::exists(cacheFilePath)); + QVERIFY(QFile::remove(testFilePath)); + + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(!obj.isNull()); + QVariant result; + QMetaObject::invokeMethod(obj.data(), "runTest", Q_RETURN_ARG(QVariant, result)); + QCOMPARE(result.toInt(), 42); +} + QTEST_GUILESS_MAIN(tst_qmlcachegen) #include "tst_qmlcachegen.moc" |