Fixes problem with single precision floats in QDataStream (Windows).

When the floating-point behavior in MSVC is set to "precise" (default),
assigning nan numbers to a float causes the bit pattern to be altered
(only affects 32bit builds). We should therefore not assign the swapped
value back to a float and use it.

Task-number: QTBUG-25950

Change-Id: I7b6cc4d546e5c8aeafdede749056358b7d639ec7
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
This commit is contained in:
Christian Strømme 2012-11-13 19:17:17 +01:00 committed by The Qt Project
parent dc2fd227ab
commit 3f936e9094
2 changed files with 49 additions and 1 deletions

View File

@ -1046,8 +1046,12 @@ QDataStream &QDataStream::operator<<(float f)
} x;
x.val1 = g;
x.val2 = qbswap(x.val2);
g = x.val1;
if (dev->write((char *)&x.val2, sizeof(float)) != sizeof(float))
q_status = WriteFailed;
return *this;
}
if (dev->write((char *)&g, sizeof(float)) != sizeof(float))
q_status = WriteFailed;
return *this;

View File

@ -195,6 +195,8 @@ private slots:
void compatibility_Qt3();
void compatibility_Qt2();
void floatingPointNaN();
private:
void writebool(QDataStream *s);
void writeQBitArray(QDataStream *s);
@ -3102,6 +3104,48 @@ void tst_QDataStream::compatibility_Qt2()
QVERIFY(in_palette.color(QPalette::Light) == Qt::green);
}
void tst_QDataStream::floatingPointNaN()
{
QDataStream::ByteOrder bo = QSysInfo::ByteOrder == QSysInfo::BigEndian
? QDataStream::LittleEndian
: QDataStream::BigEndian;
// Test and verify that values that become (s)nan's after swapping endianness
// don't change in the process.
// When compiling with e.g., MSVC (32bit) and when the fpu is used (fp:precise)
// all snan's will be converted to qnan's (default behavior).
// IF we get a snan after swapping endianness we can not copy the value to another
// float as this will cause the value to differ from the original value.
QByteArray ba;
union {
float f;
quint32 i;
} xs[2];
xs[0].i = qbswap<quint32>(0xff800001);
xs[1].i = qbswap<quint32>(0x7f800001);
{
QDataStream stream(&ba, QIODevice::WriteOnly);
stream.setByteOrder(bo);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
stream << xs[0].f;
stream << xs[1].f;
}
{
QDataStream stream(ba);
stream.setByteOrder(bo);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
float fr = 0.0f;
stream >> fr;
QCOMPARE(fr, xs[0].f);
stream >> fr;
QCOMPARE(fr, xs[1].f);
}
}
void tst_QDataStream::floatingPointPrecision()
{
QByteArray ba;