diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-11-25 09:21:27 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-25 17:34:51 +0100 |
commit | ce38c71b1c300f700a9ff004b7c163cc290ecae9 (patch) | |
tree | a347b2b4e55e8fb457855f111e5f9cd1921c0a48 | |
parent | 87da2a2526aa03dd43254730a6e675e83c7c1342 (diff) |
Fix out of bounds array access when index is integer and negativev5.2.0-rc1
When the index is a double, the branchTruncateDoubleToUInt takes care of
branching when the index is negative, but when it's an integer we need
to perform that check ourselves.
Without the patch it's rather easy to cause the application to crash.
Change-Id: If908923ddc2077b3fb3dd42350f038ff0072e8e1
Reviewed-by: Mitch Curtis <mitch.curtis@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/compiler/qv4isel_masm.cpp | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index 9d470c417d..a999dd4da1 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -1039,10 +1039,13 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR: _as->and32(Assembler::TrustedImm32(QV4::Managed::SimpleArray), Assembler::ReturnValueRegister); Assembler::Jump notSimple = _as->branch32(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm32(0)); + bool needNegativeCheck = false; Assembler::Jump fallback, fallback2; if (tindex->kind == V4IR::Temp::PhysicalRegister) { if (tindex->type == V4IR::SInt32Type) { + fallback = _as->branch32(Assembler::LessThan, (Assembler::RegisterID)tindex->index, Assembler::TrustedImm32(0)); _as->move((Assembler::RegisterID) tindex->index, Assembler::ScratchRegister); + needNegativeCheck = true; } else { // double, convert and check if it's a int fallback2 = _as->branchTruncateDoubleToUint32((Assembler::FPRegisterID) tindex->index, Assembler::ScratchRegister); @@ -1068,13 +1071,17 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR: isInteger.link(_as); _as->or32(Assembler::TrustedImm32(0), Assembler::ScratchRegister); + needNegativeCheck = true; } // get data, ScratchRegister holds index addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase); _as->load64(addr, Assembler::ReturnValueRegister); Address arrayDataLen(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayDataLen)); - Assembler::Jump outOfRange = _as->branch32(Assembler::GreaterThanOrEqual, Assembler::ScratchRegister, arrayDataLen); + Assembler::Jump outOfRange; + if (needNegativeCheck) + outOfRange = _as->branch32(Assembler::LessThan, Assembler::ScratchRegister, Assembler::TrustedImm32(0)); + Assembler::Jump outOfRange2 = _as->branch32(Assembler::GreaterThanOrEqual, Assembler::ScratchRegister, arrayDataLen); Address arrayData(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData)); _as->load64(arrayData, Assembler::ReturnValueRegister); Q_ASSERT(sizeof(Property) == (1<<4)); @@ -1092,7 +1099,9 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR: Assembler::Jump done = _as->jump(); emptyValue.link(_as); - outOfRange.link(_as); + if (outOfRange.isSet()) + outOfRange.link(_as); + outOfRange2.link(_as); if (fallback.isSet()) fallback.link(_as); if (fallback2.isSet()) |