From 06bb5f19bfe686cb149150a2c1a94699ea3e1413 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Fri, 26 Apr 2024 17:25:25 +0200 Subject: [PATCH] QDataStream::readBytes: do not leak the memory in case of bad_alloc The algorithm was leaking the previous buffer if the attempt to allocate a new one failed with std::bad_alloc. Wrap the buffer allocations into std::unique_ptr, so that we do not leak the buffer in case of bad_alloc. This patch is not changing the behavior of QDataStream, so it's NOT handling the bad_alloc exception, and also does not change the state of the buffer in case the exception occurs. Pick-to: 6.5 Change-Id: I5558a6d03768094e4ee83ca47cacf4e09c36f1cf Reviewed-by: Ivan Solovev Reviewed-by: Marc Mutz (cherry picked from commit e176dd78fd2f253eb2625585b2bd90b5713e5984) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/serialization/qdatastream.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp index 5896b8408d0..8465fefa221 100644 --- a/src/corelib/serialization/qdatastream.cpp +++ b/src/corelib/serialization/qdatastream.cpp @@ -1113,28 +1113,22 @@ QDataStream &QDataStream::readBytes(char *&s, qint64 &l) qsizetype step = 1024 * 1024; qsizetype allocated = 0; - char *prevBuf = nullptr; - char *curBuf = nullptr; + std::unique_ptr curBuf = nullptr; constexpr qsizetype StepIncreaseThreshold = std::numeric_limits::max() / 2; do { qsizetype blockSize = qMin(step, len - allocated); - prevBuf = curBuf; - curBuf = new char[allocated + blockSize + 1]; - if (prevBuf) { - memcpy(curBuf, prevBuf, allocated); - delete [] prevBuf; - } - if (readBlock(curBuf + allocated, blockSize) != blockSize) { - delete [] curBuf; + const qsizetype n = allocated + blockSize + 1; + if (const auto prevBuf = std::exchange(curBuf, std::make_unique(n))) + memcpy(curBuf.get(), prevBuf.get(), allocated); + if (readBlock(curBuf.get() + allocated, blockSize) != blockSize) return *this; - } allocated += blockSize; if (step <= StepIncreaseThreshold) step *= 2; } while (allocated < len); - s = curBuf; + s = curBuf.release(); s[len] = '\0'; l = len; return *this;