When `split_domain_account` receives a `str->Buffer=L""` with `str->Length=0` the pointer `p` gets already set in the initial assignment two bytes before the allocated memory in line 1209.
Therefore the `if (*p == '\')` accesses invalid memory.
``` ================================================================= ==advapi32_test.exe==1208==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7e89077e01ee at pc 0x6fffff6bb20f bp 0x7ffffe1ff3e0 sp 0x7ffffe1ff428 READ of size 2 at 0x7e89077e01ee thread T0 #0 0x6fffff6bb20e in split_domain_account .../wine/dlls/advapi32/security.c:1212:9 #1 0x6fffff6babe5 in lookup_local_wellknown_name .../wine/dlls/advapi32/security.c:1271:5 #2 0x6fffff6affe0 in lookup_name .../wine/dlls/advapi32/lsa.c:404:11 #3 0x6fffff6b0bbf in LsaLookupSids .../wine/dlls/advapi32/lsa.c:644:17 #4 0x00014002688e in test_LsaLookupSids .../wine/dlls/advapi32/tests/lsa.c:379:14 #5 0x000140024b17 in func_lsa .../wine/dlls/advapi32/tests/lsa.c:514:5 #6 0x00014009f9ee in run_test .../wine/include/wine/test.h:765:5 #7 0x00014009f531 in main .../wine/include/wine/test.h:884:12 #8 0x0001400a0ea3 in mainCRTStartup .../wine/dlls/msvcrt/crt_main.c:58:11 #9 0x6fffffc3565e in BaseThreadInitThunk .../wine/dlls/kernel32/thread.c:61:24 #10 0x6fffffdbbb1a in call_seh_handlers .../wine/dlls/ntdll/signal_x86_64.c:223:28
0x7e89077e01ee is located 2 bytes before 2-byte region [0x7e89077e01f0,0x7e89077e01f2) allocated by thread T0 here: #0 0x6ffffe84aa83 in HeapAlloc /home/runner/work/llvm-mingw/llvm-mingw/llvm-project/compiler-rt\lib/asan/asan_malloc_win.cpp:230:3 #1 0x6ffffe44016b in msvcrt_heap_alloc .../wine/dlls/msvcrt/heap.c:71:12 #2 0x6ffffe440739 in malloc .../wine/dlls/msvcrt/heap.c:436:15 #3 0x6fffff6b0afa in LsaLookupSids .../wine/dlls/advapi32/lsa.c:636:24 #4 0x00014002688e in test_LsaLookupSids .../wine/dlls/advapi32/tests/lsa.c:379:14 #5 0x000140024b17 in func_lsa .../wine/dlls/advapi32/tests/lsa.c:514:5 #6 0x00014009f9ee in run_test .../wine/include/wine/test.h:765:5 #7 0x00014009f531 in main .../wine/include/wine/test.h:884:12 #8 0x0001400a0ea3 in mainCRTStartup .../wine/dlls/msvcrt/crt_main.c:58:11 #9 0x6fffffc3565e in BaseThreadInitThunk .../wine/dlls/kernel32/thread.c:61:24 #10 0x6fffffdbbb1a in call_seh_handlers .../wine/dlls/ntdll/signal_x86_64.c:223:28
SUMMARY: AddressSanitizer: heap-buffer-overflow .../wine/dlls/advapi32/security.c:1212:9 in split_domain_account Shadow bytes around the buggy address: 0x7e89077dff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7e89077dff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7e89077e0000: fa fa 00 00 fa fa 02 fa fa fa 04 fa fa fa 02 fa 0x7e89077e0080: fa fa 04 fa fa fa 02 fa fa fa 04 fa fa fa 02 fa 0x7e89077e0100: fa fa 04 fa fa fa 02 fa fa fa 04 fa fa fa 00 00 =>0x7e89077e0180: fa fa fd fd fa fa fd fd fa fa fd fd fa[fa]02 fa 0x7e89077e0200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7e89077e0280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7e89077e0300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7e89077e0380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7e89077e0400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==advapi32_test.exe==1208==ABORTING ```
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/advapi32/security.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index fe6ba62d228..b7cb25c5007 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -1210,7 +1210,7 @@ static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STR
while (p > str->Buffer && *p != '\') p--;
- if (*p == '\') + if (p >= str->Buffer && *p == '\') { domain->Buffer = str->Buffer; domain->Length = (p - str->Buffer) * sizeof(WCHAR);