diff options
| author | Marc Mutz <[email protected]> | 2025-12-03 14:08:16 +0100 |
|---|---|---|
| committer | Marc Mutz <[email protected]> | 2025-12-04 20:37:47 +0000 |
| commit | afd765ee5908b66de765e53179777ab2c3c91647 (patch) | |
| tree | ce3a70504d14662a48f64480815afe839a7173a1 | |
| parent | 9d6828e9257325b011352a6d6d1a1e0da62f976b (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.cpp | 3 | ||||
| -rw-r--r-- | tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp | 77 |
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" |
