summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Martin Hansen <nielsm@indvikleren.dk>2019-02-06 21:09:02 +0100
committerGitHub <noreply@github.com>2019-02-06 21:09:02 +0100
commitdb2c0ccae08d830b654b4db93e554ca98e6003c5 (patch)
treeff10f6feed7898b5f10634452a14d770eca3c598
parente3b440c9c50b39092a2f887dba9370b21369f2cb (diff)
downloadopenttd-db2c0ccae08d830b654b4db93e554ca98e6003c5.tar.xz
Fix fdc2e85: Double close of file handles
When unpacking downloaded content, the downloaded .gz file was being opened with `fopen`, the OS file handle given to zlib, and then afterwards zlib told to close the file. But the `FILE *` object was never closed with `fclose`, meaning the stdio library would have a hanging file object, whose file handle was now invalid or referred to a different file. This caused asserts during shutdown with Microsoft's C library in debug mode. Fix this by properly duplicating the OS handle and `fclose`ing the `FILE *` object, before giving the handle to zlib.
-rw-r--r--src/network/network_content.cpp15
1 files changed, 6 insertions, 9 deletions
diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp
index e998aaeaf..551abb442 100644
--- a/src/network/network_content.cpp
+++ b/src/network/network_content.cpp
@@ -404,10 +404,14 @@ static bool GunzipFile(const ContentInfo *ci)
{
#if defined(WITH_ZLIB)
bool ret = true;
+
+ /* Need to open the file with fopen() to support non-ASCII on Windows. */
FILE *ftmp = fopen(GetFullFilename(ci, true), "rb");
if (ftmp == NULL) return false;
+ /* Duplicate the handle, and close the FILE*, to avoid double-closing the handle later. */
+ gzFile fin = gzdopen(dup(fileno(ftmp)), "rb");
+ fclose(ftmp);
- gzFile fin = gzdopen(fileno(ftmp), "rb");
FILE *fout = fopen(GetFullFilename(ci, false), "wb");
if (fin == NULL || fout == NULL) {
@@ -444,14 +448,7 @@ static bool GunzipFile(const ContentInfo *ci)
}
}
- if (fin != NULL) {
- /* Closes ftmp too! */
- gzclose(fin);
- } else if (ftmp != NULL) {
- /* In case the gz stream was opened correctly this will
- * be closed by gzclose. */
- fclose(ftmp);
- }
+ if (fin != NULL) gzclose(fin);
if (fout != NULL) fclose(fout);
return ret;