summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qbytearray.cpp
diff options
context:
space:
mode:
authorRobert Griebl <rgriebl@trolltech.com>2009-09-10 14:14:59 (GMT)
committerRobert Griebl <rgriebl@trolltech.com>2009-09-11 11:18:52 (GMT)
commite2411ebd04bf9a55e6e3b24cc7886e597521d473 (patch)
tree76344082302b32f21977bd0b57e2546c8abed2a8 /src/corelib/tools/qbytearray.cpp
parenta5a27973b1e4df62217ed510229b0d8dfa70e354 (diff)
downloadQt-e2411ebd04bf9a55e6e3b24cc7886e597521d473.zip
Qt-e2411ebd04bf9a55e6e3b24cc7886e597521d473.tar.gz
Qt-e2411ebd04bf9a55e6e3b24cc7886e597521d473.tar.bz2
Out of memory fix for qUncompress
qUncompress shouldn't crash when running out of memory, since it might deal with buffers which are not under user control (same behavior as Qt 4.5). It will however throw a std::bad_alloc exception if Qt is compiled with exception handling. Reviewed-by: Harald Fernengel Reviewed-by: Ralf Engels Reviewed-by: Lars Knoll
Diffstat (limited to 'src/corelib/tools/qbytearray.cpp')
-rw-r--r--src/corelib/tools/qbytearray.cpp54
1 files changed, 33 insertions, 21 deletions
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 6d55ef9..d8557e5 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -47,6 +47,7 @@
#include "qlocale.h"
#include "qlocale_p.h"
#include "qunicodetables_p.h"
+#include "qscopedpointer.h"
#ifndef QT_NO_DATASTREAM
#include <qdatastream.h>
#endif
@@ -535,38 +536,49 @@ QByteArray qUncompress(const uchar* data, int nbytes)
ulong expectedSize = (data[0] << 24) | (data[1] << 16) |
(data[2] << 8) | (data[3] );
ulong len = qMax(expectedSize, 1ul);
- QByteArray baunzip;
- int res;
- do {
- QT_TRY {
- baunzip.resize(len);
- res = ::uncompress((uchar*)baunzip.data(), &len,
- (uchar*)data+4, nbytes-4);
- } QT_CATCH (const std::bad_alloc &) {
- res = Z_MEM_ERROR;
+ QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d;
+
+ forever {
+ ulong alloc = len;
+ d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc))));
+ if (!d) {
+ // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
+ qWarning("qUncompress: could not allocate enough memory to uncompress data");
+ return QByteArray();
}
+ int res = ::uncompress((uchar*)d->array, &len,
+ (uchar*)data+4, nbytes-4);
+
switch (res) {
case Z_OK:
- if ((int)len != baunzip.size())
- baunzip.resize(len);
- break;
+ if (len != alloc) {
+ d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len))));
+ if (!d) {
+ // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
+ qWarning("qUncompress: could not allocate enough memory to uncompress data");
+ return QByteArray();
+ }
+ }
+ d->ref = 1;
+ d->alloc = d->size = len;
+ d->data = d->array;
+
+ return QByteArray(d.take(), 0, 0);
+
case Z_MEM_ERROR:
qWarning("qUncompress: Z_MEM_ERROR: Not enough memory");
- break;
+ return QByteArray();
+
case Z_BUF_ERROR:
len *= 2;
- break;
+ continue;
+
case Z_DATA_ERROR:
qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted");
- break;
+ return QByteArray();
}
- } while (res == Z_BUF_ERROR);
-
- if (res != Z_OK)
- baunzip = QByteArray();
-
- return baunzip;
+ }
}
#endif