diff options
author | Marius Storm-Olsen <marius@trolltech.com> | 2009-07-01 09:49:51 (GMT) |
---|---|---|
committer | Marius Storm-Olsen <marius@trolltech.com> | 2009-07-01 09:51:13 (GMT) |
commit | cfadf08a6c06ce319f6144e724f45e4923e72778 (patch) | |
tree | 672f5e0515b2b0cf718aca773eb87f9f4f738f0e /src/corelib | |
parent | 5ae330b6546dabada53c394b53ce9513f552a8a5 (diff) | |
download | Qt-cfadf08a6c06ce319f6144e724f45e4923e72778.zip Qt-cfadf08a6c06ce319f6144e724f45e4923e72778.tar.gz Qt-cfadf08a6c06ce319f6144e724f45e4923e72778.tar.bz2 |
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 <marius@trolltech.com>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 9 | ||||
-rw-r--r-- | 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 f0a3fec..e2708c3 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 657abd1..a71f284 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<wchar_t *>(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() |