From cfadf08a6c06ce319f6144e724f45e4923e72778 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 1 Jul 2009 11:49:51 +0200 Subject: [PATCH] Handle application paths larger than MAX_PATH, and fix potential buffer overflow These days we can easily get very long paths, so we should support application paths as long as needed. There was also a potention exploit in that if the path was MAX_PATH or larger, the string would not be \0 terminated (see MSDN docs for GetModuleFileName), and thus cause problems in QString::fromWCharArray(). Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/corelib/kernel/qcoreapplication.cpp | 9 ++----- src/corelib/kernel/qcoreapplication_win.cpp | 40 ++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index f0a3feceff..e2708c3316 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1741,13 +1741,8 @@ QString QCoreApplication::applicationFilePath() if (!d->cachedApplicationFilePath.isNull()) return d->cachedApplicationFilePath; -#if defined( Q_WS_WIN ) - wchar_t module_name[MAX_PATH]; - GetModuleFileName(0, module_name, MAX_PATH); - module_name[MAX_PATH] = 0; - QFileInfo filePath = QString::fromWCharArray(module_name); - - d->cachedApplicationFilePath = filePath.filePath(); +#if defined(Q_WS_WIN) + d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath(); return d->cachedApplicationFilePath; #elif defined(Q_WS_MAC) QString qAppFileName_str = qAppFileName(); diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 657abd1393..a71f2845ff 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -76,9 +76,43 @@ Q_CORE_EXPORT int qWinAppCmdShow() // get main window sho Q_CORE_EXPORT QString qAppFileName() // get application file name { - wchar_t buffer[MAX_PATH]; - GetModuleFileName(0, buffer, MAX_PATH); - return QString::fromWCharArray(buffer); + // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths + // up to, and including MAX_PATH size perfectly fine with string termination, as well + // as easily detect if the file path is indeed larger than MAX_PATH, in which case we + // need to use the heap instead. This is a work-around, since contrary to what the + // MSDN documentation states, GetModuleFileName sometimes doesn't set the + // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if + // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH. + // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal + // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use + // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok). + wchar_t buffer[MAX_PATH + 2]; + DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1); + buffer[MAX_PATH + 1] = 0; + + if (v == 0) + return QString(); + else if (v <= MAX_PATH) + return QString::fromWCharArray(buffer); + + // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap + wchar_t *b = 0; + int i = 1; + size_t size; + do { + ++i; + size = MAX_PATH * i; + b = reinterpret_cast(realloc(b, (size + 1) * sizeof(wchar_t))); + if (b) + v = GetModuleFileName(NULL, b, size); + } while (b && v == size); + + if (b) + *(b + size) = 0; + QString res = QString::fromWCharArray(b); + free(b); + + return res; } void set_winapp_name() -- 2.11.4.GIT