[DBGHELP] Fix default search path handling. CORE-17073

* Allow NULL search path in SymSetSearchPath
* Use . instead of concrete current directory
* Use _NT_ALT_SYMBOL_PATH variable
* Add some tests
This commit is contained in:
Thomas Faber 2021-11-15 20:11:42 -05:00
parent ab7b004d51
commit 4601d94801
No known key found for this signature in database
GPG key ID: 076E7C3D44720826
2 changed files with 128 additions and 37 deletions

View file

@ -191,6 +191,43 @@ struct cpu* cpu_find(DWORD machine)
return NULL; return NULL;
} }
static WCHAR* make_default_search_path(void)
{
WCHAR* search_path;
WCHAR* p;
unsigned sym_path_len;
unsigned alt_sym_path_len;
sym_path_len = GetEnvironmentVariableW(L"_NT_SYMBOL_PATH", NULL, 0);
alt_sym_path_len = GetEnvironmentVariableW(L"_NT_ALT_SYMBOL_PATH", NULL, 0);
/* The default symbol path is ".[;%_NT_SYMBOL_PATH%][;%_NT_ALT_SYMBOL_PATH%]".
* If the variables exist, the lengths include a null-terminator. We use that
* space for the semicolons, and only add the initial dot and the final null. */
search_path = HeapAlloc(GetProcessHeap(), 0,
(1 + sym_path_len + alt_sym_path_len + 1) * sizeof(WCHAR));
if (!search_path) return NULL;
p = search_path;
*p++ = L'.';
if (sym_path_len)
{
*p++ = L';';
GetEnvironmentVariableW(L"_NT_SYMBOL_PATH", p, sym_path_len);
p += sym_path_len - 1;
}
if (alt_sym_path_len)
{
*p++ = L';';
GetEnvironmentVariableW(L"_NT_ALT_SYMBOL_PATH", p, alt_sym_path_len);
p += alt_sym_path_len - 1;
}
*p = L'\0';
return search_path;
}
/****************************************************************** /******************************************************************
* SymSetSearchPathW (DBGHELP.@) * SymSetSearchPathW (DBGHELP.@)
* *
@ -198,14 +235,24 @@ struct cpu* cpu_find(DWORD machine)
BOOL WINAPI SymSetSearchPathW(HANDLE hProcess, PCWSTR searchPath) BOOL WINAPI SymSetSearchPathW(HANDLE hProcess, PCWSTR searchPath)
{ {
struct process* pcs = process_find_by_handle(hProcess); struct process* pcs = process_find_by_handle(hProcess);
WCHAR* search_path_buffer;
if (!pcs) return FALSE; if (!pcs) return FALSE;
if (!searchPath) return FALSE;
if (searchPath)
{
search_path_buffer = HeapAlloc(GetProcessHeap(), 0,
(lstrlenW(searchPath) + 1) * sizeof(WCHAR));
if (!search_path_buffer) return FALSE;
lstrcpyW(search_path_buffer, searchPath);
}
else
{
search_path_buffer = make_default_search_path();
if (!search_path_buffer) return FALSE;
}
HeapFree(GetProcessHeap(), 0, pcs->search_path); HeapFree(GetProcessHeap(), 0, pcs->search_path);
pcs->search_path = lstrcpyW(HeapAlloc(GetProcessHeap(), 0, pcs->search_path = search_path_buffer;
(lstrlenW(searchPath) + 1) * sizeof(WCHAR)),
searchPath);
return TRUE; return TRUE;
} }
@ -217,16 +264,19 @@ BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PCSTR searchPath)
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
unsigned len; unsigned len;
WCHAR* sp; WCHAR* sp = NULL;
len = MultiByteToWideChar(CP_ACP, 0, searchPath, -1, NULL, 0); if (searchPath)
if ((sp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
{ {
len = MultiByteToWideChar(CP_ACP, 0, searchPath, -1, NULL, 0);
sp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (!sp) return FALSE;
MultiByteToWideChar(CP_ACP, 0, searchPath, -1, sp, len); MultiByteToWideChar(CP_ACP, 0, searchPath, -1, sp, len);
ret = SymSetSearchPathW(hProcess, sp);
HeapFree(GetProcessHeap(), 0, sp);
} }
ret = SymSetSearchPathW(hProcess, sp);
HeapFree(GetProcessHeap(), 0, sp);
return ret; return ret;
} }
@ -448,31 +498,7 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP
} }
else else
{ {
unsigned size; pcs->search_path = make_default_search_path();
unsigned len;
static const WCHAR sym_path[] = {'_','N','T','_','S','Y','M','B','O','L','_','P','A','T','H',0};
static const WCHAR alt_sym_path[] = {'_','N','T','_','A','L','T','E','R','N','A','T','E','_','S','Y','M','B','O','L','_','P','A','T','H',0};
pcs->search_path = HeapAlloc(GetProcessHeap(), 0, (len = MAX_PATH) * sizeof(WCHAR));
while ((size = GetCurrentDirectoryW(len, pcs->search_path)) >= len)
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (len *= 2) * sizeof(WCHAR));
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (size + 1) * sizeof(WCHAR));
len = GetEnvironmentVariableW(sym_path, NULL, 0);
if (len)
{
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (size + 1 + len + 1) * sizeof(WCHAR));
pcs->search_path[size] = ';';
GetEnvironmentVariableW(sym_path, pcs->search_path + size + 1, len);
size += 1 + len;
}
len = GetEnvironmentVariableW(alt_sym_path, NULL, 0);
if (len)
{
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, (size + 1 + len + 1) * sizeof(WCHAR));
pcs->search_path[size] = ';';
GetEnvironmentVariableW(alt_sym_path, pcs->search_path + size + 1, len);
}
} }
pcs->lmodules = NULL; pcs->lmodules = NULL;

View file

@ -132,12 +132,77 @@ static void test_stack_walk(void)
#endif /* __i386__ || __x86_64__ */ #endif /* __i386__ || __x86_64__ */
static void test_search_path(void)
{
char search_path[128];
BOOL ret;
/* The default symbol path is ".[;%_NT_SYMBOL_PATH%][;%_NT_ALT_SYMBOL_PATH%]".
* We unset both variables earlier so should simply get "." */
ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
ok(ret == TRUE, "ret = %d\n", ret);
ok(!strcmp(search_path, "."), "Got search path '%s', expected '.'\n", search_path);
/* Set an arbitrary search path */
ret = SymSetSearchPath(GetCurrentProcess(), "W:\\");
ok(ret == TRUE, "ret = %d\n", ret);
ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
ok(ret == TRUE, "ret = %d\n", ret);
ok(!strcmp(search_path, "W:\\"), "Got search path '%s', expected 'W:\\'\n", search_path);
/* Setting to NULL resets to the default */
ret = SymSetSearchPath(GetCurrentProcess(), NULL);
ok(ret == TRUE, "ret = %d\n", ret);
ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
ok(ret == TRUE, "ret = %d\n", ret);
ok(!strcmp(search_path, "."), "Got search path '%s', expected '.'\n", search_path);
/* With _NT_SYMBOL_PATH */
SetEnvironmentVariableA("_NT_SYMBOL_PATH", "X:\\");
ret = SymSetSearchPath(GetCurrentProcess(), NULL);
ok(ret == TRUE, "ret = %d\n", ret);
ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
ok(ret == TRUE, "ret = %d\n", ret);
ok(!strcmp(search_path, ".;X:\\"), "Got search path '%s', expected '.;X:\\'\n", search_path);
/* With both _NT_SYMBOL_PATH and _NT_ALT_SYMBOL_PATH */
SetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", "Y:\\");
ret = SymSetSearchPath(GetCurrentProcess(), NULL);
ok(ret == TRUE, "ret = %d\n", ret);
ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
ok(ret == TRUE, "ret = %d\n", ret);
ok(!strcmp(search_path, ".;X:\\;Y:\\"), "Got search path '%s', expected '.;X:\\;Y:\\'\n", search_path);
/* With just _NT_ALT_SYMBOL_PATH */
SetEnvironmentVariableA("_NT_SYMBOL_PATH", NULL);
ret = SymSetSearchPath(GetCurrentProcess(), NULL);
ok(ret == TRUE, "ret = %d\n", ret);
ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
ok(ret == TRUE, "ret = %d\n", ret);
ok(!strcmp(search_path, ".;Y:\\"), "Got search path '%s', expected '.;Y:\\'\n", search_path);
/* Restore original search path */
SetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", NULL);
ret = SymSetSearchPath(GetCurrentProcess(), NULL);
ok(ret == TRUE, "ret = %d\n", ret);
ret = SymGetSearchPath(GetCurrentProcess(), search_path, ARRAY_SIZE(search_path));
ok(ret == TRUE, "ret = %d\n", ret);
ok(!strcmp(search_path, "."), "Got search path '%s', expected '.'\n", search_path);
}
START_TEST(dbghelp) START_TEST(dbghelp)
{ {
BOOL ret = SymInitialize(GetCurrentProcess(), NULL, TRUE); BOOL ret;
/* Don't let the user's environment influence our symbol path */
SetEnvironmentVariableA("_NT_SYMBOL_PATH", NULL);
SetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", NULL);
ret = SymInitialize(GetCurrentProcess(), NULL, TRUE);
ok(ret, "got error %u\n", GetLastError()); ok(ret, "got error %u\n", GetLastError());
test_stack_walk(); test_stack_walk();
test_search_path();
ret = SymCleanup(GetCurrentProcess()); ret = SymCleanup(GetCurrentProcess());
ok(ret, "got error %u\n", GetLastError()); ok(ret, "got error %u\n", GetLastError());