From c57befe80d7e044bc9d48f72ff4c377e948f6ad7 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sat, 4 May 2019 19:39:24 +0200 Subject: [PATCH] When opening file make sure it's actually a file, fixes #394 ... and not a directory, which can cause crashes. --- src/common/header/shared.h | 7 +------ src/common/shared/shared.c | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/common/header/shared.h b/src/common/header/shared.h index 117053a1..ae762532 100644 --- a/src/common/header/shared.h +++ b/src/common/header/shared.h @@ -254,13 +254,8 @@ int Q_strlcat(char *dst, const char *src, int size); /* ============================================= */ -/* Unicode wrappers around fopen(). */ - -#ifdef _WIN32 +/* Unicode wrappers that also make sure it's a regular file around fopen(). */ FILE *Q_fopen(const char *file, const char *mode); -#else -#define Q_fopen(file, mode) fopen(file, mode) -#endif /* ============================================= */ diff --git a/src/common/shared/shared.c b/src/common/shared/shared.c index 08da4d05..7de02faa 100644 --- a/src/common/shared/shared.c +++ b/src/common/shared/shared.c @@ -1149,7 +1149,9 @@ Q_strlcat(char *dst, const char *src, int size) */ #ifdef _WIN32 #include - +#include +#include +#include FILE *Q_fopen(const char *file, const char *mode) { WCHAR wfile[MAX_OSPATH]; @@ -1161,12 +1163,33 @@ FILE *Q_fopen(const char *file, const char *mode) { if (MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, 16) > 0) { - return _wfopen(wfile, wmode); + // make sure it's a regular file and not a directory or sth, see #394 + struct _stat buf; + int statret = _wstat(wfile, &buf); + if((statret == 0 && (buf.st_mode & _S_IFREG) != 0) || (statret == -1 && errno == ENOENT)) + { + return _wfopen(wfile, wmode); + } } } return NULL; } +#else +#include +#include +FILE *Q_fopen(const char *file, const char *mode) +{ + // make sure it's a regular file and not a directory or sth, see #394 + struct stat statbuf; + int statret = stat(file, &statbuf); + // (it's ok if it doesn't exist though, maybe we wanna write/create) + if((statret == -1 && errno != ENOENT) || (statret == 0 && (statbuf.st_mode & S_IFREG) == 0)) + { + return NULL; + } + return fopen(file, mode); +} #endif /*