aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2018-01-26 11:28:06 +0100
committerErik Verbruggen <erik.verbruggen@qt.io>2018-02-05 09:15:25 +0000
commit8501993e5275076d9163a7e2f8bab9ba2f187f72 (patch)
tree3db7ebe28102dd1e952a6a511f5d70488adfbf4d
parentc2bd33af9fb548ff20bf34323271baa89cbc8a55 (diff)
QML: Collapse all NaNs into one single (encoded) NaN
The idea of NaN boxing is to use one single NaN as a "true" NaN, and all others as a boxed value. So when encoding some NaN, be sure to use that one "true" NaN. Otherwise, it will be interpreted as an encoded value. Task-number: QTBUG-65998 Change-Id: Ia6e4641be180f3d626c40a57b473f181358e04db Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4value_p.h4
-rw-r--r--tests/auto/qml/qqmlecmascript/data/nans.qml5
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp15
3 files changed, 24 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 9adad881a1..94233d4ddb 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -56,6 +56,8 @@
#include "qv4global_p.h"
#include <private/qv4heap_p.h>
+#include <private/qnumeric_p.h>
+
#if QT_POINTER_SIZE == 8
#define QV4_USE_64_BIT_VALUE_ENCODING
#endif
@@ -362,6 +364,8 @@ public:
return d;
}
QML_NEARLY_ALWAYS_INLINE void setDouble(double d) {
+ if (qt_is_nan(d))
+ d = qt_qnan();
memcpy(&_val, &d, 8);
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
_val ^= NaNEncodeMask;
diff --git a/tests/auto/qml/qqmlecmascript/data/nans.qml b/tests/auto/qml/qqmlecmascript/data/nans.qml
new file mode 100644
index 0000000000..ece69f2d79
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/nans.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+ property var prop: undefined
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index db7ec87c02..14447383c1 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -338,6 +338,7 @@ private slots:
void freeze_empty_object();
void singleBlockLoops();
void qtbug_60547();
+ void anotherNaN();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -8266,6 +8267,20 @@ void tst_qqmlecmascript::qtbug_60547()
QCOMPARE(object->property("counter"), QVariant(int(1)));
}
+void tst_qqmlecmascript::anotherNaN()
+{
+ QQmlComponent component(&engine, testFileUrl("nans.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
+ object->setProperty("prop", std::numeric_limits<double>::quiet_NaN()); // don't crash
+
+ std::uint64_t anotherNaN = 0xFFFFFF01000000F7ul;
+ double d;
+ std::memcpy(&d, &anotherNaN, sizeof(d));
+ QVERIFY(std::isnan(d));
+ object->setProperty("prop", d); // don't crash
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"