Fix UB in QFSFileEnginePrivate::writeFdFh()
Apparently, it is considered valid to call the function with 'data' set to nullptr, and 'len' to zero. But doing so invokes undefined behavior because nullptr is passed to fwrite(). Fix by protecting the loops with 'if (len)'. Found by UBSan: qtbase/src/corelib/io/qfsfileengine.cpp:732:84: runtime error: null pointer passed as argument 1, which is declared to never be null Change-Id: Idfe23875c868ebb21d2164550de3304d2f01e9df Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
71ea41f999
commit
b4ab4868bc
|
|
@ -724,29 +724,33 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len)
|
|||
|
||||
qint64 writtenBytes = 0;
|
||||
|
||||
if (fh) {
|
||||
// Buffered stdlib mode.
|
||||
if (len) { // avoid passing nullptr to fwrite() or QT_WRITE() (UB)
|
||||
|
||||
size_t result;
|
||||
do {
|
||||
result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
|
||||
writtenBytes += result;
|
||||
} while (result == 0 ? errno == EINTR : writtenBytes < len);
|
||||
if (fh) {
|
||||
// Buffered stdlib mode.
|
||||
|
||||
} else if (fd != -1) {
|
||||
// Unbuffered stdio mode.
|
||||
size_t result;
|
||||
do {
|
||||
result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh);
|
||||
writtenBytes += result;
|
||||
} while (result == 0 ? errno == EINTR : writtenBytes < len);
|
||||
|
||||
} else if (fd != -1) {
|
||||
// Unbuffered stdio mode.
|
||||
|
||||
SignedIOType result;
|
||||
do {
|
||||
// calculate the chunk size
|
||||
// on Windows or 32-bit no-largefile Unix, we'll need to read in chunks
|
||||
// we limit to the size of the signed type, otherwise we could get a negative number as a result
|
||||
quint64 wantedBytes = quint64(len) - quint64(writtenBytes);
|
||||
UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
|
||||
if (chunkSize > wantedBytes)
|
||||
chunkSize = wantedBytes;
|
||||
result = QT_WRITE(fd, data + writtenBytes, chunkSize);
|
||||
} while (result > 0 && (writtenBytes += result) < len);
|
||||
}
|
||||
|
||||
SignedIOType result;
|
||||
do {
|
||||
// calculate the chunk size
|
||||
// on Windows or 32-bit no-largefile Unix, we'll need to read in chunks
|
||||
// we limit to the size of the signed type, otherwise we could get a negative number as a result
|
||||
quint64 wantedBytes = quint64(len) - quint64(writtenBytes);
|
||||
UnsignedIOType chunkSize = std::numeric_limits<SignedIOType>::max();
|
||||
if (chunkSize > wantedBytes)
|
||||
chunkSize = wantedBytes;
|
||||
result = QT_WRITE(fd, data + writtenBytes, chunkSize);
|
||||
} while (result > 0 && (writtenBytes += result) < len);
|
||||
}
|
||||
|
||||
if (len && writtenBytes == 0) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue