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 /src/qml/compiler | |
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 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 8 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 16 |
2 files changed, 12 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp index 05bbf25292..03105d2b71 100644 --- a/src/qml/compiler/qv4bytecodegenerator.cpp +++ b/src/qml/compiler/qv4bytecodegenerator.cpp @@ -82,7 +82,7 @@ void BytecodeGenerator::packInstruction(I &i) Wide } width = Normal; for (int n = 0; n < nMembers; ++n) { - if (width == Normal && (static_cast<char>(instructionsAsInts[n]) != instructionsAsInts[n])) + if (width == Normal && (static_cast<qint8>(instructionsAsInts[n]) != instructionsAsInts[n])) width = Wide; } char *code = i.packed; @@ -91,7 +91,7 @@ void BytecodeGenerator::packInstruction(I &i) *reinterpret_cast<uchar *>(code) = type; ++code; for (int n = 0; n < nMembers; ++n) { - char v = static_cast<char>(instructionsAsInts[n]); + qint8 v = static_cast<qint8>(instructionsAsInts[n]); memcpy(code, &v, 1); code += 1; } @@ -113,7 +113,7 @@ void BytecodeGenerator::adjustJumpOffsets() continue; Q_ASSERT(i.linkedLabel != -1 && labels.at(i.linkedLabel) != -1); const auto &linkedInstruction = instructions.at(labels.at(i.linkedLabel)); - char *c = i.packed + i.offsetForJump; + qint8 *c = reinterpret_cast<qint8*>(i.packed + i.offsetForJump); int jumpOffset = linkedInstruction.position - (i.position + i.size); // qDebug() << "adjusting jump offset for instruction" << index << i.position << i.size << "offsetForJump" << i.offsetForJump << "target" // << labels.at(i.linkedLabel) << linkedInstruction.position << "jumpOffset" << jumpOffset; @@ -123,7 +123,7 @@ void BytecodeGenerator::adjustJumpOffsets() memcpy(c, &jumpOffset, sizeof(int)); } else { Q_ASSERT(i.offsetForJump == i.size - 1); - char o = jumpOffset; + qint8 o = jumpOffset; Q_ASSERT(o == jumpOffset); *c = o; } diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index a9de71e7ad..789f875ba7 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -366,9 +366,9 @@ QT_BEGIN_NAMESPACE MOTH_ADJUST_CODE(int, nargs); \ MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ goto op_main_##name; \ - op_char_##name: \ - MOTH_ADJUST_CODE(char, nargs); \ - MOTH_DECODE_ARGS(name, char, nargs, __VA_ARGS__) \ + op_byte_##name: \ + MOTH_ADJUST_CODE(qint8, nargs); \ + MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ op_main_##name: \ ; \ @@ -380,10 +380,10 @@ QT_BEGIN_NAMESPACE MOTH_ADJUST_CODE(int, nargs); \ MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ goto op_main_##name; \ - op_char_##name: \ + op_byte_##name: \ base_ptr = code; \ - MOTH_ADJUST_CODE(char, nargs); \ - MOTH_DECODE_ARGS(name, char, nargs, __VA_ARGS__) \ + MOTH_ADJUST_CODE(qint8, nargs); \ + MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ op_main_##name: \ ; \ @@ -408,7 +408,7 @@ QT_BEGIN_NAMESPACE #define COLLECT_LABELS(instr) \ INSTR_##instr(GET_LABEL) #define GET_LABEL_INSTRUCTION(name, ...) \ - &&op_char_##name, + &&op_byte_##name, #define COLLECT_LABELS_WIDE(instr) \ INSTR_##instr(GET_LABEL_WIDE) #define GET_LABEL_WIDE_INSTRUCTION(name, ...) \ @@ -428,7 +428,7 @@ QT_BEGIN_NAMESPACE #define MOTH_INSTR_CASE_AND_JUMP(instr) \ INSTR_##instr(GET_CASE_AND_JUMP) #define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \ - case static_cast<uchar>(Instr::Type::name): goto op_char_##name; + case static_cast<uchar>(Instr::Type::name): goto op_byte_##name; #define MOTH_INSTR_CASE_AND_JUMP_WIDE(instr) \ INSTR_##instr(GET_CASE_AND_JUMP_WIDE) #define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \ |