From 64714ea431f2fd355ed27edc69dba4e992511e75 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 4 Nov 2016 00:11:59 +0100 Subject: QV4String: properly detect overflow when trying to convert to an array index A wrong overflow detection caused strings like "240000000000" to pass the conversion, even though they would not fit into a uint when converted into base-10. This mis-conversion to uint then caused all sorts of side effects (broken comparisons, wrong listing of properties, and so on). So, properly fix the overflow detection by using our numeric private functions. Change-Id: Icbf67ac68cf5785d6c77b433c7a45aed5285a8c2 Task-number: QTBUG-56830 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4string.cpp | 12 +++++++++--- src/qmldevtools/qmldevtools.pro | 2 +- tests/auto/qml/qjsvalue/tst_qjsvalue.cpp | 27 +++++++++++++++++++++++++++ tests/auto/qml/qjsvalue/tst_qjsvalue.h | 2 ++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 24a13ddd10..da3c783808 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -40,6 +40,7 @@ #include "qv4stringobject_p.h" #endif #include +#include using namespace QV4; @@ -57,10 +58,15 @@ static uint toArrayIndex(const QChar *ch, const QChar *end) uint x = ch->unicode() - '0'; if (x > 9) return UINT_MAX; - uint n = i*10 + x; - if (n < i) - // overflow + + uint n; + // n = i * 10 + x, with overflow checking + if (mul_overflow(i, 10u, &n)) return UINT_MAX; + + if (add_overflow(n, x, &n)) + return UINT_MAX; + i = n; ++ch; } diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro index 3f199e5971..42fe53ed60 100644 --- a/src/qmldevtools/qmldevtools.pro +++ b/src/qmldevtools/qmldevtools.pro @@ -1,6 +1,6 @@ option(host_build) TARGET = QtQmlDevTools -QT = core +QT = core core-private CONFIG += static internal_module qmldevtools_build # Don't use pch because the auto-generated header refers to QtBootstrap, diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp index bf9bd18807..b9a9fec6d9 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp @@ -1371,6 +1371,33 @@ void tst_QJSValue::hasProperty_changePrototype() QVERIFY(obj.hasOwnProperty("foo")); } +void tst_QJSValue::hasProperty_QTBUG56830_data() +{ + QTest::addColumn("key"); + QTest::addColumn("lookup"); + + QTest::newRow("bugreport-1") << QStringLiteral("240000000000") << QStringLiteral("3776798720"); + QTest::newRow("bugreport-2") << QStringLiteral("240000000001") << QStringLiteral("3776798721"); + QTest::newRow("biggest-ok-before-bug") << QStringLiteral("238609294221") << QStringLiteral("2386092941"); + QTest::newRow("smallest-bugged") << QStringLiteral("238609294222") << QStringLiteral("2386092942"); + QTest::newRow("biggest-bugged") << QStringLiteral("249108103166") << QStringLiteral("12884901886"); + QTest::newRow("smallest-ok-after-bug") << QStringLiteral("249108103167") << QStringLiteral("12884901887"); +} + +void tst_QJSValue::hasProperty_QTBUG56830() +{ + QFETCH(QString, key); + QFETCH(QString, lookup); + + QJSEngine eng; + const QJSValue value(42); + + QJSValue obj = eng.newObject(); + obj.setProperty(key, value); + QVERIFY(obj.hasProperty(key)); + QVERIFY(!obj.hasProperty(lookup)); +} + void tst_QJSValue::deleteProperty_basic() { QJSEngine eng; diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.h b/tests/auto/qml/qjsvalue/tst_qjsvalue.h index 16667ff344..485577bf97 100644 --- a/tests/auto/qml/qjsvalue/tst_qjsvalue.h +++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.h @@ -97,6 +97,8 @@ private slots: void hasProperty_basic(); void hasProperty_globalObject(); void hasProperty_changePrototype(); + void hasProperty_QTBUG56830_data(); + void hasProperty_QTBUG56830(); void deleteProperty_basic(); void deleteProperty_globalObject(); -- cgit v1.2.3