diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-01-06 16:53:40 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-01-08 09:28:57 +0100 |
commit | 2d566bb65def5b759bb4d93d767c4377bc6c5e0a (patch) | |
tree | 75e9485d9786c9ec89cb24e309897922a5d96498 | |
parent | 5e9a7246acb44a04c51bf066fc2e24368ca47204 (diff) |
V4: Avoid integer overflow on typed array length check
Change-Id: I370b4c4bd0d7962878849ca7c5edef6cb36eca25
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4typedarray.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qml/qjsengine/tst_qjsengine.cpp | 36 |
2 files changed, 41 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index 7d33167762..a5a720abc0 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -1416,7 +1416,8 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b, if (scope.engine->hasException || l != len) return scope.engine->throwTypeError(); - if (offset + l > a->length()) + const uint aLength = a->length(); + if (offset > aLength || l > aLength - offset) RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"))); uint idx = 0; @@ -1446,7 +1447,9 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b, return scope.engine->throwTypeError(); uint l = srcTypedArray->length(); - if (offset + l > a->length()) + + const uint aLength = a->length(); + if (offset > aLength || l > aLength - offset) RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"))); char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize; diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index e379cb1f11..66a526fda8 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -262,6 +262,7 @@ private slots: void tostringRecursionCheck(); void arrayIncludesWithLargeArray(); void printCircularArray(); + void typedArraySet(); public: Q_INVOKABLE QJSValue throwingCppMethod1(); @@ -5107,6 +5108,41 @@ void tst_QJSEngine::applyOnHugeArray() QCOMPARE(value.toString(), "RangeError: Array too large for apply()."); } +void tst_QJSEngine::typedArraySet() +{ + QJSEngine engine; + const auto value = engine.evaluate( + "(function() {" + " var length = 0xffffffe;" + " var offset = 0xfffffff0;" + " var e1;" + " var e2;" + " try {" + " var source1 = new Int8Array(length);" + " var target1 = new Int8Array(length);" + " target1.set(source1, offset);" + " } catch (intError) {" + " e1 = intError;" + " }" + " try {" + " var source2 = new Array(length);" + " var target2 = new Int8Array(length);" + " target2.set(source2, offset);" + " } catch (arrayError) {" + " e2 = arrayError;" + " }" + " return [e1, e2];" + "})();" + ); + + QVERIFY(value.isArray()); + for (int i = 0; i < 2; ++i) { + const auto error = value.property(i); + QVERIFY(error.isError()); + QCOMPARE(error.toString(), "RangeError: TypedArray.set: out of range"); + } +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" |