diff options
-rw-r--r-- | src/qml/jsruntime/qv4arraybuffer.cpp | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4typedarray.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 14 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 1 |
4 files changed, 24 insertions, 4 deletions
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 59a2b9d913..95dd5444c3 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -94,7 +94,8 @@ ReturnedValue ArrayBufferCtor::method_isView(const FunctionObject *, const Value void Heap::ArrayBuffer::init(size_t length) { Object::init(); - data = QTypedArrayData<char>::allocate(length + 1); + if (length < UINT_MAX) + data = QTypedArrayData<char>::allocate(length + 1); if (!data) { internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory")); return; diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 81e4deb463..ea83f4940b 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -219,9 +219,12 @@ ReturnedValue TypedArrayCtor::callAsConstructor(const FunctionObject *f, const V if (!argc || !argv[0].isObject()) { // ECMA 6 22.2.1.1 - double l = argc ? argv[0].toNumber() : 0; + qint64 l = argc ? argv[0].toIndex() : 0; if (scope.engine->hasException) return Encode::undefined(); + // ### lift UINT_MAX restriction + if (l < 0 || l > UINT_MAX) + return scope.engine->throwRangeError(QLatin1String("Index out of range.")); uint len = (uint)l; if (l != len) scope.engine->throwRangeError(QStringLiteral("Non integer length for typed array.")); @@ -315,7 +318,10 @@ ReturnedValue TypedArrayCtor::callAsConstructor(const FunctionObject *f, const V return scope.engine->throwTypeError(); uint elementSize = operations[that->d()->type].bytesPerElement; - Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(l * elementSize)); + size_t bufferSize; + if (mul_overflow(size_t(l), size_t(elementSize), &bufferSize)) + return scope.engine->throwRangeError(QLatin1String("new TypedArray: invalid length")); + Scoped<ArrayBuffer> newBuffer(scope, scope.engine->newArrayBuffer(bufferSize)); if (scope.engine->hasException) return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 97c6ea23ff..c3a927fa91 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -402,6 +402,7 @@ public: inline int toInt32() const; inline unsigned int toUInt32() const; qint64 toLength() const; + inline qint64 toIndex() const; bool toBoolean() const { if (integerCompatible()) @@ -833,6 +834,19 @@ inline qint64 Value::toLength() const return static_cast<qint64>(i); } +inline qint64 Value::toIndex() const +{ + qint64 idx; + if (Q_LIKELY(integerCompatible())) { + idx = int_32(); + } else { + idx = static_cast<qint64>(Primitive::toInteger(isDouble() ? doubleValue() : toNumberImpl())); + } + if (idx > (static_cast<qint64>(1) << 53) - 1) + idx = -1; + return idx; +} + inline double Value::toInteger() const { if (integerCompatible()) diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 00b9b7f513..5d4afe5538 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -2819,7 +2819,6 @@ built-ins/TypedArrays/ctors/buffer-arg/use-custom-proto-if-object.js fails built-ins/TypedArrays/ctors/buffer-arg/use-default-proto-if-custom-proto-is-not-object.js fails built-ins/TypedArrays/ctors/length-arg/custom-proto-access-throws.js fails built-ins/TypedArrays/ctors/length-arg/proto-from-ctor-realm.js fails -built-ins/TypedArrays/ctors/length-arg/toindex-length.js fails built-ins/TypedArrays/ctors/length-arg/undefined-newtarget-throws.js fails built-ins/TypedArrays/ctors/length-arg/use-custom-proto-if-object.js fails built-ins/TypedArrays/ctors/length-arg/use-default-proto-if-custom-proto-is-not-object.js fails |