diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2014-09-20 16:49:24 +0200 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2014-09-22 18:57:18 +0200 |
commit | bc5a1c6d3fc36d9d48c719895c2061e052ead17e (patch) | |
tree | 0da5599b8e458aa1faf2de81948522346f09101d /src/corelib/io/qfsfileengine.cpp | |
parent | 8f622fef415cacb50f826268282a276502dcc607 (diff) |
QFile: fix undefined behavior when closing a buffered file
C11 ยง7.21.3.4 [Files] says that
The value of a pointer to a FILE object is indeterminate
after the associated file is closed
POSIX.1-2013 reinforces by saying that
After the call to fclose(), any use of stream results
in undefined behavior.
This means we can't call fclose() again on a FILE *,
even if fclose() returned EOF and set errno to EINTR.
Change-Id: I282f4ff926e3c134729defa290c80d42431e97ce
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Diffstat (limited to 'src/corelib/io/qfsfileengine.cpp')
-rw-r--r-- | src/corelib/io/qfsfileengine.cpp | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 1ae182a4c1..e198cd6d75 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -168,10 +168,7 @@ QFSFileEngine::~QFSFileEngine() Q_D(QFSFileEngine); if (d->closeFileHandle) { if (d->fh) { - int ret; - do { - ret = fclose(d->fh); - } while (ret == EOF && errno == EINTR); + fclose(d->fh); } else if (d->fd != -1) { int ret; do { @@ -375,15 +372,14 @@ bool QFSFileEnginePrivate::closeFdFh() // Close the file if we created the handle. if (closeFileHandle) { int ret; - do { - if (fh) { - // Close buffered file. - ret = fclose(fh) != 0 ? -1 : 0; - } else { - // Close unbuffered file. - ret = QT_CLOSE(fd); - } - } while (ret == -1 && errno == EINTR); + + if (fh) { + // Close buffered file. + ret = fclose(fh); + } else { + // Close unbuffered file. + EINTR_LOOP(ret, QT_CLOSE(fd)); + } // We must reset these guys regardless; calling close again after a // failed close causes crashes on some systems. |