summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <[email protected]>2025-12-03 14:08:16 +0100
committerMarc Mutz <[email protected]>2025-12-04 20:37:47 +0000
commitafd765ee5908b66de765e53179777ab2c3c91647 (patch)
treece3a70504d14662a48f64480815afe839a7173a1
parent9d6828e9257325b011352a6d6d1a1e0da62f976b (diff)
QVectorND: do not assert when deserialization yields NaN or ±∞
These types happily hold NaNs and infinites, if you know what you're doing, and so we can stream such objects out. We cannot then refuse to stream them back in again. [ChangeLog][QtGui][QVector2D/QVector3D/QVector4D] Fixed a bug in the QDataStream operator that could lead to an assertion failure (program termination) on reading back previously streamed out objects that contain NaN or infinity values. Amends 7a738daa97436478a21b5dd31ba2312b2cb2df41. Pick-to: 6.10 6.8 6.5 Fixes: QTBUG-142431 Change-Id: I790d7fbc46e5bd48a2cbd7e8a26d9c90c5fe05b9 Reviewed-by: Ivan Solovev <[email protected]>
-rw-r--r--src/gui/math3d/qvectornd.cpp3
-rw-r--r--tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp77
2 files changed, 77 insertions, 3 deletions
diff --git a/src/gui/math3d/qvectornd.cpp b/src/gui/math3d/qvectornd.cpp
index dcd7bdbcf80..ec836cfa56e 100644
--- a/src/gui/math3d/qvectornd.cpp
+++ b/src/gui/math3d/qvectornd.cpp
@@ -467,7 +467,6 @@ QDataStream &operator>>(QDataStream &stream, QVector2D &vector)
float x, y;
stream >> x;
stream >> y;
- Q_ASSERT(qIsFinite(x) && qIsFinite(y));
vector.setX(x);
vector.setY(y);
return stream;
@@ -1098,7 +1097,6 @@ QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
stream >> x;
stream >> y;
stream >> z;
- Q_ASSERT(qIsFinite(x) && qIsFinite(y) && qIsFinite(z));
vector.setX(x);
vector.setY(y);
vector.setZ(z);
@@ -1627,7 +1625,6 @@ QDataStream &operator>>(QDataStream &stream, QVector4D &vector)
stream >> y;
stream >> z;
stream >> w;
- Q_ASSERT(qIsFinite(x) && qIsFinite(y) && qIsFinite(z) && qIsFinite(w));
vector.setX(x);
vector.setY(y);
vector.setZ(z);
diff --git a/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp
index 3272ffac0ee..18d8b604dff 100644
--- a/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp
+++ b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp
@@ -4,6 +4,9 @@
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
+
+#include <QtCore/qdatastream.h>
+
#ifdef QVARIANT_H
# error "This test requires qvector{2,3,4}d.h to not include qvariant.h"
#endif
@@ -162,6 +165,8 @@ private slots:
void metaTypes();
void structuredBinding();
+ void nonFiniteValuesStreamingRoundTrip_data();
+ void nonFiniteValuesStreamingRoundTrip();
};
// Test the creation of QVector2D objects in various ways:
@@ -2759,6 +2764,78 @@ void tst_QVectorND::structuredBinding()
}
}
+void tst_QVectorND::nonFiniteValuesStreamingRoundTrip_data()
+{
+ QTest::addColumn<float>("value");
+
+ constexpr auto inf = std::numeric_limits<float>::infinity();
+ constexpr auto NaN = std::numeric_limits<float>::quiet_NaN();
+
+ QTest::addRow("+∞") << +inf;
+ QTest::addRow("-∞") << -inf;
+ QTest::addRow("NaN") << NaN;
+
+}
+
+void tst_QVectorND::nonFiniteValuesStreamingRoundTrip()
+{
+ QFETCH(const float, value);
+
+ const QVector2D i2{value, value};
+ const QVector3D i3{value, value, value};
+ const QVector4D i4{value, value, value, value};
+
+ QByteArray buffer;
+
+ {
+ QDataStream s(&buffer, QIODevice::WriteOnly);
+ s << i2 << i3 << i4;
+ QCOMPARE(s.status(), QDataStream::Status::Ok);
+ }
+
+ {
+ QVector2D o2 = {0, 0};
+ QVector3D o3 = {1, 0, -1};
+ QVector4D o4 = {0, 1, 2, 3};
+
+ QDataStream s(&buffer, QIODevice::ReadOnly);
+ s >> o2;
+ QCOMPARE(s.status(), QDataStream::Status::Ok);
+ s >> o3;
+ QCOMPARE(s.status(), QDataStream::Status::Ok);
+ s >> o4;
+ QCOMPARE(s.status(), QDataStream::Status::Ok);
+
+ constexpr auto convert_to_binary = [](float v) {
+ uint r;
+ static_assert(sizeof v == sizeof r);
+ memcpy(&r, &v, sizeof v);
+ return r;
+ };
+
+ #define CHECK(n, what) \
+ do { \
+ const auto i ## n ## what = convert_to_binary(i ## n . what ()); \
+ const auto o ## n ## what = convert_to_binary(o ## n . what ()); \
+ QCOMPARE(i ## n ## what, o ## n ## what); \
+ } while (false)
+
+ CHECK(2, x);
+ CHECK(2, y);
+
+ CHECK(3, x);
+ CHECK(3, y);
+ CHECK(3, z);
+
+ CHECK(4, x);
+ CHECK(4, y);
+ CHECK(4, z);
+ CHECK(4, w);
+
+ #undef CHECK
+ }
+}
+
QTEST_APPLESS_MAIN(tst_QVectorND)
#include "tst_qvectornd.moc"