From ce38c71b1c300f700a9ff004b7c163cc290ecae9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 25 Nov 2013 09:21:27 +0100 Subject: Fix out of bounds array access when index is integer and negative 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 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4isel_masm.cpp | 13 +++++++++++-- 1 file 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()) -- cgit v1.2.3