mirror of https://github.com/OpenTTD/OpenTTD
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.pull/7187/head
parent
e3b440c9c5
commit
db2c0ccae0
|
@ -404,10 +404,14 @@ static bool GunzipFile(const ContentInfo *ci)
|
||||||
{
|
{
|
||||||
#if defined(WITH_ZLIB)
|
#if defined(WITH_ZLIB)
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
|
/* Need to open the file with fopen() to support non-ASCII on Windows. */
|
||||||
FILE *ftmp = fopen(GetFullFilename(ci, true), "rb");
|
FILE *ftmp = fopen(GetFullFilename(ci, true), "rb");
|
||||||
if (ftmp == NULL) return false;
|
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");
|
FILE *fout = fopen(GetFullFilename(ci, false), "wb");
|
||||||
|
|
||||||
if (fin == NULL || fout == NULL) {
|
if (fin == NULL || fout == NULL) {
|
||||||
|
@ -444,14 +448,7 @@ static bool GunzipFile(const ContentInfo *ci)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fin != NULL) {
|
if (fin != NULL) gzclose(fin);
|
||||||
/* 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 (fout != NULL) fclose(fout);
|
if (fout != NULL) fclose(fout);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue