diff options
author | Trond Kjernaasen <trond@trolltech.com> | 2009-05-27 09:11:57 (GMT) |
---|---|---|
committer | Trond Kjernaasen <trond@trolltech.com> | 2009-05-27 09:15:43 (GMT) |
commit | 2c1b11f2192fd48da01a1093a7cb4a848de43c8a (patch) | |
tree | 207b7c975794e50ddf23fa3dc11983342be12de8 | |
parent | 8bf5a6986db852525582713cc2f2a760df4fdc60 (diff) | |
download | Qt-2c1b11f2192fd48da01a1093a7cb4a848de43c8a.zip Qt-2c1b11f2192fd48da01a1093a7cb4a848de43c8a.tar.gz Qt-2c1b11f2192fd48da01a1093a7cb4a848de43c8a.tar.bz2 |
Fixed aliasing pointer corruption in QDataStream.
Use a union instead of an unsafe cast when swapping the bytes in
the QDataStream streaming operators. The old seems to cause problems
with Link Time Code Generation optimizations with the MSVC compilers.
Task-number: 247708
Reviewed-by: Samuel
Reviewed-by: Thiago
BT: yes
-rw-r--r-- | src/corelib/io/qdatastream.cpp | 92 |
1 files changed, 77 insertions, 15 deletions
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index b203899..e324ffe 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -622,11 +622,16 @@ QDataStream &QDataStream::operator>>(qint16 &i) setStatus(ReadPastEnd); } } else { - register uchar *p = (uchar *)(&i); + union { + qint16 val1; + char val2[2]; + } x; + char *p = x.val2; char b[2]; if (dev->read(b, 2) == 2) { *p++ = b[1]; *p = b[0]; + i = x.val1; } else { setStatus(ReadPastEnd); } @@ -660,13 +665,18 @@ QDataStream &QDataStream::operator>>(qint32 &i) setStatus(ReadPastEnd); } } else { // swap bytes - uchar *p = (uchar *)(&i); + union { + qint32 val1; + char val2[4]; + } x; + char *p = x.val2; char b[4]; if (dev->read(b, 4) == 4) { *p++ = b[3]; *p++ = b[2]; *p++ = b[1]; *p = b[0]; + i = x.val1; } else { setStatus(ReadPastEnd); } @@ -703,7 +713,12 @@ QDataStream &QDataStream::operator>>(qint64 &i) setStatus(ReadPastEnd); } } else { // swap bytes - uchar *p = (uchar *)(&i); + union { + qint64 val1; + char val2[8]; + } x; + + char *p = x.val2; char b[8]; if (dev->read(b, 8) == 8) { *p++ = b[7]; @@ -714,6 +729,7 @@ QDataStream &QDataStream::operator>>(qint64 &i) *p++ = b[2]; *p++ = b[1]; *p = b[0]; + i = x.val1; } else { setStatus(ReadPastEnd); } @@ -751,13 +767,19 @@ QDataStream &QDataStream::operator>>(float &f) setStatus(ReadPastEnd); } } else { // swap bytes - uchar *p = (uchar *)(&f); + union { + float val1; + char val2[4]; + } x; + + char *p = x.val2; char b[4]; if (dev->read(b, 4) == 4) { *p++ = b[3]; *p++ = b[2]; *p++ = b[1]; *p = b[0]; + f = x.val1; } else { setStatus(ReadPastEnd); } @@ -788,7 +810,11 @@ QDataStream &QDataStream::operator>>(double &f) setStatus(ReadPastEnd); } } else { // swap bytes - register uchar *p = (uchar *)(&f); + union { + double val1; + char val2[8]; + } x; + char *p = x.val2; char b[8]; if (dev->read(b, 8) == 8) { *p++ = b[7]; @@ -799,13 +825,18 @@ QDataStream &QDataStream::operator>>(double &f) *p++ = b[2]; *p++ = b[1]; *p = b[0]; + f = x.val1; } else { setStatus(ReadPastEnd); } } #else //non-standard floating point format - register uchar *p = (uchar *)(&f); + union { + double val1; + char val2[8]; + } x; + char *p = x.val2; char b[8]; if (dev->read(b, 8) == 8) { if (noswap) { @@ -827,6 +858,7 @@ QDataStream &QDataStream::operator>>(double &f) *p++ = b[Q_DF(1)]; *p = b[Q_DF(0)]; } + f = x.val1; } else { setStatus(ReadPastEnd); } @@ -970,7 +1002,12 @@ QDataStream &QDataStream::operator<<(qint16 i) if (noswap) { dev->write((char *)&i, sizeof(qint16)); } else { // swap bytes - register uchar *p = (uchar *)(&i); + union { + qint16 val1; + char val2[2]; + } x; + x.val1 = i; + char *p = x.val2; char b[2]; b[1] = *p++; b[0] = *p; @@ -992,7 +1029,12 @@ QDataStream &QDataStream::operator<<(qint32 i) if (noswap) { dev->write((char *)&i, sizeof(qint32)); } else { // swap bytes - register uchar *p = (uchar *)(&i); + union { + qint32 val1; + char val2[4]; + } x; + x.val1 = i; + char *p = x.val2; char b[4]; b[3] = *p++; b[2] = *p++; @@ -1022,13 +1064,18 @@ QDataStream &QDataStream::operator<<(qint64 i) { CHECK_STREAM_PRECOND(*this) if (version() < 6) { - quint32 i1 = i & 0xffffffff; - quint32 i2 = i >> 32; - *this << i2 << i1; + quint32 i1 = i & 0xffffffff; + quint32 i2 = i >> 32; + *this << i2 << i1; } else if (noswap) { // no conversion needed dev->write((char *)&i, sizeof(qint64)); } else { // swap bytes - register uchar *p = (uchar *)(&i); + union { + qint64 val1; + char val2[8]; + } x; + x.val1 = i; + char *p = x.val2; char b[8]; b[7] = *p++; b[6] = *p++; @@ -1077,7 +1124,12 @@ QDataStream &QDataStream::operator<<(float f) if (noswap) { // no conversion needed dev->write((char *)&g, sizeof(float)); } else { // swap bytes - register uchar *p = (uchar *)(&g); + union { + float val1; + char val2[4]; + } x; + x.val1 = f; + char *p = x.val2; char b[4]; b[3] = *p++; b[2] = *p++; @@ -1103,7 +1155,12 @@ QDataStream &QDataStream::operator<<(double f) if (noswap) { dev->write((char *)&f, sizeof(double)); } else { - register uchar *p = (uchar *)(&f); + union { + double val1; + char val2[8]; + } x; + x.val1 = f; + char *p = x.val2; char b[8]; b[7] = *p++; b[6] = *p++; @@ -1116,7 +1173,12 @@ QDataStream &QDataStream::operator<<(double f) dev->write(b, 8); } #else - register uchar *p = (uchar *)(&f); + union { + double val1; + char val2[8]; + } x; + x.val1 = f; + char *p = x.val2; char b[8]; if (noswap) { b[Q_DF(0)] = *p++; |