Alexandre Julliard : kernel32: Fix buffer overflows in K32GetModuleFileNameExA/W.
Alexandre Julliard
julliard at winehq.org
Mon Apr 30 14:13:08 CDT 2012
Module: wine
Branch: master
Commit: d08f34cd8ecd883a0f0c6bd9b150d92407f0f7c9
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d08f34cd8ecd883a0f0c6bd9b150d92407f0f7c9
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Apr 30 14:19:57 2012 +0200
kernel32: Fix buffer overflows in K32GetModuleFileNameExA/W.
---
dlls/kernel32/module.c | 31 ++++++++++++++++++++++++-----
dlls/psapi/tests/psapi_main.c | 42 +++++++++++++++++++++++++++++++++++++---
2 files changed, 63 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c
index 6b91a4c..57a24ba 100644
--- a/dlls/kernel32/module.c
+++ b/dlls/kernel32/module.c
@@ -1247,17 +1247,26 @@ DWORD WINAPI K32GetModuleFileNameExW(HANDLE process, HMODULE module,
LPWSTR file_name, DWORD size)
{
LDR_MODULE ldr_module;
+ DWORD len;
+
+ if (!size) return 0;
if(!get_ldr_module(process, module, &ldr_module))
return 0;
- size = min(ldr_module.FullDllName.Length / sizeof(WCHAR), size);
+ len = ldr_module.FullDllName.Length / sizeof(WCHAR);
+ if (size <= len)
+ {
+ len = size;
+ size--;
+ }
+
if (!ReadProcessMemory(process, ldr_module.FullDllName.Buffer,
file_name, size * sizeof(WCHAR), NULL))
return 0;
file_name[size] = 0;
- return size;
+ return len;
}
/***********************************************************************
@@ -1267,32 +1276,42 @@ DWORD WINAPI K32GetModuleFileNameExA(HANDLE process, HMODULE module,
LPSTR file_name, DWORD size)
{
WCHAR *ptr;
+ DWORD len;
TRACE("(hProcess=%p, hModule=%p, %p, %d)\n", process, module, file_name, size);
- if (!file_name || !size) return 0;
+ if (!file_name || !size)
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0;
+ }
if ( process == GetCurrentProcess() )
{
- DWORD len = GetModuleFileNameA( module, file_name, size );
+ len = GetModuleFileNameA( module, file_name, size );
if (size) file_name[size - 1] = '\0';
return len;
}
if (!(ptr = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)))) return 0;
- if (!K32GetModuleFileNameExW(process, module, ptr, size))
+ len = K32GetModuleFileNameExW(process, module, ptr, size);
+ if (!len)
{
file_name[0] = '\0';
}
else
{
if (!WideCharToMultiByte( CP_ACP, 0, ptr, -1, file_name, size, NULL, NULL ))
+ {
file_name[size - 1] = 0;
+ len = size;
+ }
+ else if (len < size) len = strlen( file_name );
}
HeapFree(GetProcessHeap(), 0, ptr);
- return strlen(file_name);
+ return len;
}
/***********************************************************************
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index 1944065..8db695e 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -49,6 +49,7 @@ static BOOL (WINAPI *pEnumProcesses)(DWORD*, DWORD, DWORD*);
static BOOL (WINAPI *pEnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD);
static DWORD (WINAPI *pGetModuleBaseNameA)(HANDLE, HMODULE, LPSTR, DWORD);
static DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE, HMODULE, LPSTR, DWORD);
+static DWORD (WINAPI *pGetModuleFileNameExW)(HANDLE, HMODULE, LPWSTR, DWORD);
static BOOL (WINAPI *pGetModuleInformation)(HANDLE, HMODULE, LPMODULEINFO, DWORD);
static DWORD (WINAPI *pGetMappedFileNameA)(HANDLE, LPVOID, LPSTR, DWORD);
static DWORD (WINAPI *pGetMappedFileNameW)(HANDLE, LPVOID, LPWSTR, DWORD);
@@ -67,6 +68,7 @@ static BOOL InitFunctionPtrs(HMODULE hpsapi)
PSAPI_GET_PROC(EnumProcesses);
PSAPI_GET_PROC(GetModuleBaseNameA);
PSAPI_GET_PROC(GetModuleFileNameExA);
+ PSAPI_GET_PROC(GetModuleFileNameExW);
PSAPI_GET_PROC(GetModuleInformation);
PSAPI_GET_PROC(GetMappedFileNameA);
PSAPI_GET_PROC(GetMappedFileNameW);
@@ -471,18 +473,22 @@ static void test_GetModuleFileNameEx(void)
{
HMODULE hMod = GetModuleHandle(NULL);
char szModExPath[MAX_PATH+1], szModPath[MAX_PATH+1];
+ WCHAR buffer[MAX_PATH];
DWORD ret;
-
+
SetLastError(0xdeadbeef);
- pGetModuleFileNameExA(NULL, hMod, szModExPath, sizeof(szModExPath));
+ ret = pGetModuleFileNameExA(NULL, hMod, szModExPath, sizeof(szModExPath));
+ ok( !ret, "GetModuleFileNameExA succeeded\n" );
ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
SetLastError(0xdeadbeef);
- pGetModuleFileNameExA(hpQI, hMod, szModExPath, sizeof(szModExPath));
+ ret = pGetModuleFileNameExA(hpQI, hMod, szModExPath, sizeof(szModExPath));
+ ok( !ret, "GetModuleFileNameExA succeeded\n" );
ok(GetLastError() == ERROR_ACCESS_DENIED, "expected error=ERROR_ACCESS_DENIED but got %d\n", GetLastError());
SetLastError(0xdeadbeef);
- pGetModuleFileNameExA(hpQV, hBad, szModExPath, sizeof(szModExPath));
+ ret = pGetModuleFileNameExA(hpQV, hBad, szModExPath, sizeof(szModExPath));
+ ok( !ret, "GetModuleFileNameExA succeeded\n" );
ok(GetLastError() == ERROR_INVALID_HANDLE, "expected error=ERROR_INVALID_HANDLE but got %d\n", GetLastError());
ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, sizeof(szModExPath));
@@ -492,6 +498,34 @@ static void test_GetModuleFileNameEx(void)
GetModuleFileNameA(NULL, szModPath, sizeof(szModPath));
ok(!strncmp(szModExPath, szModPath, MAX_PATH),
"szModExPath=\"%s\" szModPath=\"%s\"\n", szModExPath, szModPath);
+
+ SetLastError(0xdeadbeef);
+ memset( szModExPath, 0xcc, sizeof(szModExPath) );
+ ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, 4 );
+ ok( ret == 4, "wrong length %u\n", ret );
+ ok( broken(szModExPath[3]) /*w2kpro*/ || strlen(szModExPath) == 3,
+ "szModExPath=\"%s\" ret=%d\n", szModExPath, ret );
+ ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pGetModuleFileNameExA(hpQV, NULL, szModExPath, 0 );
+ ok( ret == 0, "wrong length %u\n", ret );
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ memset( buffer, 0xcc, sizeof(buffer) );
+ ret = pGetModuleFileNameExW(hpQV, NULL, buffer, 4 );
+ ok( ret == 4, "wrong length %u\n", ret );
+ ok( broken(buffer[3]) /*w2kpro*/ || lstrlenW(buffer) == 3,
+ "buffer=%s ret=%d\n", wine_dbgstr_w(buffer), ret );
+ ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ buffer[0] = 0xcc;
+ ret = pGetModuleFileNameExW(hpQV, NULL, buffer, 0 );
+ ok( ret == 0, "wrong length %u\n", ret );
+ ok(GetLastError() == 0xdeadbeef, "got error %d\n", GetLastError());
+ ok( buffer[0] == 0xcc, "buffer modified %s\n", wine_dbgstr_w(buffer) );
}
static void test_GetModuleBaseName(void)
More information about the wine-cvs
mailing list