Recently I am experimenting with an ASan instrumented Wine build (Details [here](https://gitlab.winehq.org/bernhardu/wine/-/blob/asan-pe_2024-12-29/README.md)), which was showing some issues when running the confirmance tests.
One issue seems to be `ok` statements, which if I understand it right, do evaluate the condition inside the `winetest_ok` function.
Unfortunately at that time e.g. `debugstr_w(buf)` as parameters to the `ok` statement got already executed.
This leads in some places to overrunning these buffers, especially those which initialize the whole buffer with e.g. `memset(dst, 0xcc, ...`.
This patches replace e.g. `debugstr_w(buf)` by their length limiting variant `debugstr_wn(buf, ARRAY_SIZE(buf))`.
Following is the example output of the `win32u:win32u` test: ``` wine dlls/win32u/tests/i386-windows/win32u_test.exe win32u ================================================================= ==2640==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x005cf650 at pc 0x0042d112 bp 0x005cdf34 sp 0x005cdf30 READ of size 2 at 0x005cf650 thread T0 #0 0x0042d111 in wine_dbgstr_wn .../wine/include/wine/debug.h:263:30 #1 0x0040394a in debugstr_w .../wine/include/wine/debug.h:522:65 #2 0x0040394a in test_class .../wine/dlls/win32u/tests/win32u.c:269:41 #3 0x0040394a in func_win32u .../wine/dlls/win32u/tests/win32u.c:2548:5 #4 0x00436849 in run_test .../wine/include/wine/test.h:765:5 #5 0x00436260 in main .../wine/include/wine/test.h #6 0x00437f0b in mainCRTStartup .../wine/dlls/msvcrt/crt_main.c:58:11 #7 0x7877ea3f in BaseThreadInitThunk (C:\windows\system32\kernel32.dll+0x7b80ea3f) #8 0x788fce82 in call_thread_func_wrapper (C:\windows\system32\ntdll.dll+0x7bc0ce82) #9 0x789304b4 in call_thread_func .../wine/dlls/ntdll\signal_i386.c:524:9
Address 0x005cf650 is located in stack of thread T0 at offset 5296 in frame #0 0x0040100f in func_win32u .../wine/dlls/win32u/tests/win32u.c:2518
This frame has 37 object(s): [16, 100) 'source_name.i' (line 1291) [144, 184) 'cls.i675' (line 2031) [224, 264) 'cls.i638' (line 1349) [304, 564) 'path.i' (line 1350) [640, 656) 'pi.i' (line 1351) [672, 740) 'startup.i' (line 1352) [784, 812) 'msg.i639' (line 1353) [848, 876) 'msg.i615' (line 1271) [912, 940) 'msg.i' (line 1220) [976, 1024) 'item.i' (line 1143) [1056, 2080) 'buf.i537' (line 1088) [2208, 2216) 'callback_params.i' (line 1024) [2240, 2252) 'smp.i' (line 1028) [2272, 2312) 'cls.i440' (line 1029) [2352, 2872) 'module.i' (line 891) [3008, 3528) 'res_buf.i' (line 891) [3664, 3672) 'module_str.i' (line 892) [3696, 3704) 'res_str.i' (line 892) [3728, 4752) 'bmp_bits.i' (line 893) [4880, 4884) 'width.i' (line 894) [4896, 4900) 'height.i' (line 894) [4912, 4916) 'rate.i' (line 895) [4928, 4932) 'steps.i' (line 895) [4944, 4964) 'info.i348' (line 898) [5008, 5012) 'ret_size.i' (line 752) [5024, 5056) 'buf.i234' (line 415) [5088, 5100) 'himc.i' (line 415) [5120, 5124) 'size.i' (line 417) [5136, 5144) 'name.i' (line 180) [5168, 5296) 'buf.i173' (line 181) <== Memory access at offset 5296 overflows this variable [5328, 5368) 'cls.i' (line 182) [5408, 5412) 'count.i' (line 123) [5424, 6264) 'info.i' (line 71) [6400, 6436) 'mdi.i' (line 1389) [6480, 6680) 'bufW.i' (line 1390) [6752, 6852) 'buf.i' (line 1391) [6896, 6900) 'argv' (line 2519) HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp, SEH and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow .../wine/include/wine/debug.h:263:30 in wine_dbgstr_wn Shadow bytes around the buggy address: 0x005cf380: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x005cf400: f8 f8 f8 f8 f8 f8 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 0x005cf480: f2 f2 f2 f2 f2 f2 f8 f2 f8 f2 f8 f2 f8 f2 f8 f8 0x005cf500: f8 f2 f2 f2 f2 f2 f8 f2 f8 f8 f8 f8 f2 f2 f2 f2 0x005cf580: f8 f8 f2 f2 f8 f2 00 f2 f2 f2 00 00 00 00 00 00 =>0x005cf600: 00 00 00 00 00 00 00 00 00 00[f2]f2 f2 f2 00 00 0x005cf680: 00 00 00 f2 f2 f2 f2 f2 f8 f2 f8 f8 f8 f8 f8 f8 0x005cf700: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x005cf780: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x005cf800: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x005cf880: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 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 ==2640==ABORTING ```
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/crypt32/tests/str.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c index 1f65234f400..bc83a1237fe 100644 --- a/dlls/crypt32/tests/str.c +++ b/dlls/crypt32/tests/str.c @@ -469,7 +469,7 @@ static void test_NameToStrConversionA_(unsigned int line, PCERT_NAME_BLOB pName, ok(len == strlen(expected) + 1, "line %u: Expected %d chars, got %ld.\n", line, lstrlenA(expected) + 1, len); len = CertNameToStrA(X509_ASN_ENCODING,pName, dwStrType, buffer, sizeof(buffer)); ok(len == strlen(expected) + 1, "line %u: Expected %d chars, got %ld.\n", line, lstrlenA(expected) + 1, len); - ok(!strcmp(buffer, expected), "line %u: Expected %s, got %s.\n", line, expected, buffer); + ok(!strcmp(buffer, expected), "line %u: Expected %s, got %s.\n", line, expected, wine_dbgstr_an(buffer, ARRAY_SIZE(buffer)));
memset(buffer, 0xcc, sizeof(buffer)); retlen = CertNameToStrA(X509_ASN_ENCODING, pName, dwStrType, buffer, len - 1); @@ -479,7 +479,7 @@ static void test_NameToStrConversionA_(unsigned int line, PCERT_NAME_BLOB pName, memset(buffer, 0xcc, sizeof(buffer)); retlen = CertNameToStrA(X509_ASN_ENCODING, pName, dwStrType, buffer, 0); ok(retlen == len, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen); - ok((unsigned char)buffer[0] == 0xcc, "line %u: got %s\n", line, wine_dbgstr_a(buffer)); + ok((unsigned char)buffer[0] == 0xcc, "line %u: got %s\n", line, wine_dbgstr_an(buffer, ARRAY_SIZE(buffer))); }
static BYTE encodedSimpleCN[] = {
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/crypt32/tests/str.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c index bc83a1237fe..72bbd698bd6 100644 --- a/dlls/crypt32/tests/str.c +++ b/dlls/crypt32/tests/str.c @@ -631,19 +631,19 @@ static void test_NameToStrConversionW_(unsigned int line, PCERT_NAME_BLOB pName, ok(len == expected_len, "line %u: expected %lu chars, got %lu\n", line, expected_len, len); retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, ARRAY_SIZE(buffer)); ok(retlen == len, "line %u: expected %lu chars, got %lu.\n", line, len, retlen); - ok(!wcscmp(buffer, expected), "Expected %s, got %s\n", wine_dbgstr_w(expected), wine_dbgstr_w(buffer)); + ok(!wcscmp(buffer, expected), "Expected %s, got %s\n", wine_dbgstr_w(expected), wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)));
memset(buffer, 0xcc, sizeof(buffer)); retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, len - 1); ok(retlen == len - 1, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen); ok(!wcsncmp(buffer, expected, retlen - 1), "line %u: expected %s, got %s\n", - line, wine_dbgstr_w(expected), wine_dbgstr_w(buffer)); + line, wine_dbgstr_w(expected), wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer))); ok(!buffer[retlen - 1], "line %u: string is not zero terminated.\n", line);
memset(buffer, 0xcc, sizeof(buffer)); retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, 0); ok(retlen == len, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen); - ok(buffer[0] == 0xcccc, "line %u: got %s\n", line, wine_dbgstr_w(buffer)); + ok(buffer[0] == 0xcccc, "line %u: got %s\n", line, wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer))); }
static void test_CertNameToStrW(void)
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/imm32/tests/imm32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index db73463ef49..6e50e614b6b 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -4202,7 +4202,7 @@ static void test_ImmEscape( BOOL unicode ) } else { - ok( !memcmp( bufferW, "ImeEscape", 10 ), "got bufferW %s\n", debugstr_w(bufferW) ); + ok( !memcmp( bufferW, "ImeEscape", 10 ), "got bufferW %s\n", debugstr_wn(bufferW, ARRAY_SIZE(bufferW)) ); ok_eq( 0xcdcd, bufferW[5], WORD, "%#x" ); } CHECK_CALLED( ImeEscape );
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/kernel32/tests/actctx.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index b6f43b12f1a..a51c3c8db8b 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -3421,7 +3421,7 @@ static void test_settings(void) memset( buffer, 0xcc, sizeof(buffer) ); ret = pQueryActCtxSettingsW( 0, handle, NULL, dpiAwareW, buffer, 80, &size ); ok( ret, "QueryActCtxSettingsW failed err %lu\n", GetLastError() ); - ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( size == lstrlenW( buffer ) + 1, "wrong len %Iu\n", size ); SetLastError( 0xdeadbeef ); size = 0xdead; @@ -3429,20 +3429,20 @@ static void test_settings(void) ret = pQueryActCtxSettingsW( 0, handle, NULL, dummyW, buffer, 80, &size ); ok( !ret, "QueryActCtxSettingsW succeeded\n" ); ok( GetLastError() == ERROR_SXS_KEY_NOT_FOUND, "wrong error %lu\n", GetLastError() ); - ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_w(buffer) ); + ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); SetLastError( 0xdeadbeef ); size = 0xdead; memset( buffer, 0xcc, sizeof(buffer) ); ret = pQueryActCtxSettingsW( 0, handle, namespace2005W, dpiAwareW, buffer, 80, &size ); ok( ret, "QueryActCtxSettingsW failed err %lu\n", GetLastError() ); - ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( size == ARRAY_SIZE(trueW), "wrong len %Iu\n", size ); SetLastError( 0xdeadbeef ); size = 0xdead; memset( buffer, 0xcc, sizeof(buffer) ); ret = pQueryActCtxSettingsW( 0, handle, namespace2005W, dpiAwareW, buffer, lstrlenW(trueW) + 1, &size ); ok( ret, "QueryActCtxSettingsW failed err %lu\n", GetLastError() ); - ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( size == ARRAY_SIZE(trueW), "wrong len %Iu\n", size ); SetLastError( 0xdeadbeef ); size = 0xdead; @@ -3451,21 +3451,21 @@ static void test_settings(void) ok( !ret, "QueryActCtxSettingsW succeeded\n" ); ok( GetLastError() == ERROR_SXS_KEY_NOT_FOUND || broken( GetLastError() == ERROR_INVALID_PARAMETER ), "wrong error %lu\n", GetLastError() ); - ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_w(buffer) ); + ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); SetLastError( 0xdeadbeef ); size = 0xdead; memset( buffer, 0xcc, sizeof(buffer) ); ret = pQueryActCtxSettingsW( 0, handle, NULL, dpiAwarenessW, buffer, lstrlenW(trueW) + 1, &size ); ok( !ret, "QueryActCtxSettingsW succeeded\n" ); ok( GetLastError() == ERROR_SXS_KEY_NOT_FOUND, "wrong error %lu\n", GetLastError() ); - ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_w(buffer) ); + ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); SetLastError( 0xdeadbeef ); size = 0xdead; memset( buffer, 0xcc, sizeof(buffer) ); ret = pQueryActCtxSettingsW( 0, handle, namespace2005W, dpiAwarenessW, buffer, lstrlenW(trueW) + 1, &size ); ok( !ret, "QueryActCtxSettingsW succeeded\n" ); ok( GetLastError() == ERROR_SXS_KEY_NOT_FOUND, "wrong error %lu\n", GetLastError() ); - ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_w(buffer) ); + ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); SetLastError( 0xdeadbeef ); size = 0xdead; memset( buffer, 0xcc, sizeof(buffer) ); @@ -3474,16 +3474,16 @@ static void test_settings(void) "QueryActCtxSettingsW failed err %lu\n", GetLastError() ); if (ret) { - ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( size == ARRAY_SIZE(trueW), "wrong len %Iu\n", size ); } - else ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_w(buffer) ); + else ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); SetLastError( 0xdeadbeef ); size = 0xdead; memset( buffer, 0xcc, sizeof(buffer) ); ret = pQueryActCtxSettingsW( 0, handle, NULL, dpiAwareW, buffer, lstrlenW(trueW), &size ); ok( ret, "QueryActCtxSettingsW failed err %lu\n", GetLastError() ); - ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( size == ARRAY_SIZE(trueW), "wrong len %Iu\n", size ); SetLastError( 0xdeadbeef ); size = 0xdead; @@ -3491,7 +3491,7 @@ static void test_settings(void) ret = pQueryActCtxSettingsW( 0, handle, NULL, dpiAwareW, buffer, lstrlenW(trueW) - 1, &size ); ok( !ret, "QueryActCtxSettingsW failed err %lu\n", GetLastError() ); ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %lu\n", GetLastError() ); - ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_w(buffer) ); + ok( buffer[0] == 0xcccc, "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( size == ARRAY_SIZE(trueW), "wrong len %Iu\n", size ); ReleaseActCtx(handle);
@@ -3507,7 +3507,7 @@ static void test_settings(void) memset( buffer, 0xcc, sizeof(buffer) ); ret = pQueryActCtxSettingsW( 0, handle, NULL, dpiAwareW, buffer, 80, &size ); ok( ret, "QueryActCtxSettingsW failed err %lu\n", GetLastError() ); - ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_w(buffer) ); + ok( !lstrcmpW( buffer, trueW ), "got %s\n", wine_dbgstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( size == lstrlenW( buffer ) + 1, "wrong len %Iu\n", size ); ReleaseActCtx(handle); }
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/kernel32/tests/locale.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 60fa7d99a8a..82d9edb3ebe 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -2987,16 +2987,16 @@ static void test_LocaleNameToLCID(void) pLCIDToLocaleName(GetUserDefaultLCID(), expbuff, LOCALE_NAME_MAX_LENGTH, 0); ret = pLCIDToLocaleName(LOCALE_NEUTRAL, buffer, LOCALE_NAME_MAX_LENGTH, 0); ok(ret > 0, "Expected ret > 0, got %d, error %ld\n", ret, GetLastError()); - ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_w(buffer), debugstr_w(expbuff)); + ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(expbuff));
ret = pLCIDToLocaleName(LOCALE_CUSTOM_DEFAULT, buffer, LOCALE_NAME_MAX_LENGTH, 0); ok(ret > 0, "Expected ret > 0, got %d, error %ld\n", ret, GetLastError()); - ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_w(buffer), debugstr_w(expbuff)); + ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(expbuff));
SetLastError( 0xdeadbeef ); ret = pLCIDToLocaleName(LOCALE_CUSTOM_UNSPECIFIED, buffer, LOCALE_NAME_MAX_LENGTH, 0); ok(ret > 0 || broken(!ret), /* <= win8 */ "Expected ret > 0, got %d, error %ld\n", ret, GetLastError()); - if (ret) ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_w(buffer), debugstr_w(expbuff)); + if (ret) ok( !wcscmp( buffer, expbuff ), "got %s / %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(expbuff));
SetLastError( 0xdeadbeef ); ret = pLCIDToLocaleName(LOCALE_CUSTOM_UI_DEFAULT, buffer, LOCALE_NAME_MAX_LENGTH, 0); @@ -3190,7 +3190,7 @@ static void test_LocaleNameToLCID(void) memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); - ok( !wcscmp( buffer, L"en-US" ), "wrong name %s\n", debugstr_w(buffer) ); + ok( !wcscmp( buffer, L"en-US" ), "wrong name %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); ok( str.MaximumLength == sizeof(buffer), "wrong max len %u\n", str.MaximumLength );
@@ -3201,14 +3201,14 @@ static void test_LocaleNameToLCID(void) status = pRtlLcidToLocaleName( MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), &str, 2, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); - ok( !wcscmp( buffer, L"en" ), "wrong name %s\n", debugstr_w(buffer) ); + ok( !wcscmp( buffer, L"en" ), "wrong name %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)) );
ok( IsValidLocale( 0x00010407, 0 ), "expected valid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( 0x00010407, &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); - ok( !wcscmp( buffer, L"de-DE_phoneb" ), "wrong name %s\n", debugstr_w(buffer) ); + ok( !wcscmp( buffer, L"de-DE_phoneb" ), "wrong name %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)) );
ok( !IsValidLocale( LOCALE_SYSTEM_DEFAULT, 0 ), "expected invalid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); @@ -3216,7 +3216,7 @@ static void test_LocaleNameToLCID(void) ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); LCIDToLocaleName( GetSystemDefaultLCID(), expect, ARRAY_SIZE(expect), 0 ); - ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) ); + ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(expect) );
ok( !IsValidLocale( LOCALE_USER_DEFAULT, 0 ), "expected invalid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); @@ -3224,21 +3224,21 @@ static void test_LocaleNameToLCID(void) ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); LCIDToLocaleName( GetUserDefaultLCID(), expect, ARRAY_SIZE(expect), 0 ); - ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) ); + ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(expect) );
ok( IsValidLocale( LOCALE_INVARIANT, 0 ), "expected valid\n" ); memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( LOCALE_INVARIANT, &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); - ok( !wcscmp( buffer, L"" ), "wrong name %s\n", debugstr_w(buffer) ); + ok( !wcscmp( buffer, L"" ), "wrong name %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)) );
memset( buffer, 0xcc, sizeof(buffer) ); status = pRtlLcidToLocaleName( LOCALE_CUSTOM_DEFAULT, &str, 0, 0 ); ok( status == STATUS_SUCCESS, "wrong error %lx\n", status ); ok( str.Length == wcslen(buffer) * sizeof(WCHAR), "wrong len %u\n", str.Length ); LCIDToLocaleName( GetUserDefaultLCID(), expect, ARRAY_SIZE(expect), 0 ); - ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_w(buffer), debugstr_w(expect) ); + ok( !wcscmp( buffer, expect ), "wrong name %s / %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(expect) );
status = pRtlLcidToLocaleName( LOCALE_CUSTOM_UI_DEFAULT, &str, 0, 0 ); ok( status == STATUS_SUCCESS || status == STATUS_UNSUCCESSFUL, "wrong error %lx\n", status ); @@ -3253,7 +3253,7 @@ static void test_LocaleNameToLCID(void) ok( status == STATUS_BUFFER_TOO_SMALL, "wrong error %lx\n", status ); ok( str.Length == 0xbeef, "wrong len %u\n", str.Length ); ok( str.MaximumLength == 5 * sizeof(WCHAR), "wrong len %u\n", str.MaximumLength ); - ok( buffer[0] == 0xcccc, "wrong name %s\n", debugstr_w(buffer) ); + ok( buffer[0] == 0xcccc, "wrong name %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)) );
memset( &str, 0xcc, sizeof(str) ); status = pRtlLcidToLocaleName( MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &str, 0, 1 );
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/kernel32/tests/locale.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 82d9edb3ebe..c9b9aa3600c 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -6033,13 +6033,13 @@ static void test_ResolveLocaleName(void) if (tests[i].exp) { ok( !wcscmp( buffer, tests[i].exp ) || broken( tests[i].broken ), - "%s: got %s\n", debugstr_w(tests[i].name), debugstr_w(buffer) ); + "%s: got %s\n", debugstr_w(tests[i].name), debugstr_wn(buffer, ARRAY_SIZE(buffer)) ); ok( ret == wcslen(buffer) + 1, "%s: got %u\n", debugstr_w(tests[i].name), ret ); } else { ok( !ret || broken( ret == 1 ) /* win7 */, - "%s: got %s\n", debugstr_w(tests[i].name), debugstr_w(buffer) ); + "%s: got %s\n", debugstr_w(tests[i].name), debugstr_wn(buffer, ARRAY_SIZE(buffer)) ); if (!ret) ok( GetLastError() == ERROR_INVALID_PARAMETER, "%s: wrong error %lu\n", debugstr_w(tests[i].name), GetLastError() ); @@ -6050,14 +6050,14 @@ static void test_ResolveLocaleName(void) ret = pResolveLocaleName( LOCALE_NAME_SYSTEM_DEFAULT, buffer, ARRAY_SIZE(buffer) ); ok( ret, "failed err %lu\n", GetLastError() ); GetSystemDefaultLocaleName( system, ARRAY_SIZE(system) ); - ok( !wcscmp( buffer, system ), "got wrong syslocale %s / %s\n", debugstr_w(buffer), debugstr_w(system)); + ok( !wcscmp( buffer, system ), "got wrong syslocale %s / %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(system)); ok( ret == wcslen(system) + 1, "wrong len %u / %Iu\n", ret, wcslen(system) + 1 );
SetLastError( 0xdeadbeef ); ret = pResolveLocaleName( L"en-US", buffer, 4 ); ok( !ret, "got %u\n", ret ); ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %lu\n", GetLastError() ); - ok( !wcscmp( buffer, L"en-" ), "got %s\n", debugstr_w(buffer) ); + ok( !wcscmp( buffer, L"en-" ), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)) );
SetLastError( 0xdeadbeef ); ret = pResolveLocaleName( L"en-US", NULL, 0 );
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/kernel32/tests/locale.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index c9b9aa3600c..7f81dc512f9 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -7397,11 +7397,11 @@ static void test_NormalizeString(void) dstlen = pNormalizeString( norm_forms[i], ptest->str, lstrlenW(ptest->str), NULL, 0 ); memset(dst, 0xcc, sizeof(dst)); dstlen = pNormalizeString( norm_forms[i], ptest->str, lstrlenW(ptest->str), dst, dstlen ); - ok(dstlen == lstrlenW( ptest->expected[i] ), "%s:%d: Copied length differed: was %d, should be %d\n", - wine_dbgstr_w(ptest->str), i, dstlen, lstrlenW( dst )); + ok(dstlen == lstrlenW( ptest->expected[i] ), "%s:%d: Copied length differed: was %d, should be %zu\n", + wine_dbgstr_w(ptest->str), i, dstlen, wcsnlen( dst, ARRAY_SIZE(dst) )); str_cmp = wcsncmp( ptest->expected[i], dst, dstlen ); ok( str_cmp == 0, "%s:%d: string incorrect got %s expect %s\n", wine_dbgstr_w(ptest->str), i, - wine_dbgstr_w(dst), wine_dbgstr_w(ptest->expected[i]) ); + wine_dbgstr_wn(dst, ARRAY_SIZE(dst)), wine_dbgstr_w(ptest->expected[i]) );
if (pRtlNormalizeString) {
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/msvcp140/tests/msvcp140.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/msvcp140/tests/msvcp140.c b/dlls/msvcp140/tests/msvcp140.c index d2bcd192f45..e72ac84e71f 100644 --- a/dlls/msvcp140/tests/msvcp140.c +++ b/dlls/msvcp140/tests/msvcp140.c @@ -725,7 +725,7 @@ static void test_to_wide(void) ok(!ret, "Got unexpected result %d\n", ret); ret = p_To_wide(NULL, dst); ok(!ret, "Got unexpected result %d\n", ret); - ok(!memcmp(dst, compare, sizeof(compare)), "Destination was modified: %s\n", wine_dbgstr_w(dst)); + ok(!memcmp(dst, compare, sizeof(compare)), "Destination was modified: %s\n", wine_dbgstr_wn(dst, ARRAY_SIZE(dst)));
for (i = 0; i < ARRAY_SIZE(tests); ++i) { @@ -733,7 +733,7 @@ static void test_to_wide(void) expected = MultiByteToWideChar(CP_ACP, 0, tests[i], -1, compare, ARRAY_SIZE(compare)); ok(ret == expected, "Got unexpected result %d, expected %d, test case %u\n", ret, expected, i); ok(!memcmp(dst, compare, sizeof(compare)), "Got unexpected output %s, test case %u\n", - wine_dbgstr_w(dst), i); + wine_dbgstr_wn(dst, ARRAY_SIZE(dst)), i); }
/* Output length is limited to MAX_PATH.*/ @@ -748,7 +748,7 @@ static void test_to_wide(void) expected = MultiByteToWideChar(CP_ACP, 0, longstr, -1, compare, MAX_PATH); ok(ret == expected, "Got unexpected result %d, expected %d, length %u\n", ret, expected, i); ok(!memcmp(dst, compare, sizeof(compare)), "Got unexpected output %s, length %u\n", - wine_dbgstr_w(dst), i); + wine_dbgstr_wn(dst, ARRAY_SIZE(dst)), i); } }
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/ntdll/tests/pipe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index df693d07cbd..fe398fde4f0 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -1936,7 +1936,7 @@ static void _test_file_name(unsigned line, HANDLE pipe) ok_(__FILE__,line)( iosb.Information == sizeof(name_info->FileNameLength) + sizeof(nameW), "Information = %Iu\n", iosb.Information ); ok( name_info->FileNameLength == sizeof(nameW), "FileNameLength = %lu\n", name_info->FileNameLength ); - ok( !memcmp(name_info->FileName, nameW, sizeof(nameW)), "FileName = %s\n", wine_dbgstr_w(name_info->FileName) ); + ok( !memcmp(name_info->FileName, nameW, sizeof(nameW)), "FileName = %s\n", wine_dbgstr_wn(name_info->FileName, name_info->FileNameLength) );
/* too small buffer */ memset( buffer, 0xaa, sizeof(buffer) ); @@ -1946,7 +1946,7 @@ static void _test_file_name(unsigned line, HANDLE pipe) ok( iosb.Status == STATUS_BUFFER_OVERFLOW, "Status = %lx\n", iosb.Status ); ok( iosb.Information == 20, "Information = %Iu\n", iosb.Information ); ok( name_info->FileNameLength == sizeof(nameW), "FileNameLength = %lu\n", name_info->FileNameLength ); - ok( !memcmp(name_info->FileName, nameW, 16), "FileName = %s\n", wine_dbgstr_w(name_info->FileName) ); + ok( !memcmp(name_info->FileName, nameW, 16), "FileName = %s\n", wine_dbgstr_wn(name_info->FileName, name_info->FileNameLength) );
/* too small buffer */ memset( buffer, 0xaa, sizeof(buffer) );
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/ntdll/tests/string.c | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/tests/string.c b/dlls/ntdll/tests/string.c index 3d975d12a10..525e46469ae 100644 --- a/dlls/ntdll/tests/string.c +++ b/dlls/ntdll/tests/string.c @@ -1672,104 +1672,104 @@ static void test__snwprintf(void) res = p_snwprintf(buffer, lstrlenW(teststring), teststring); ok(res == lstrlenW(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenW(teststring)); ok(!wcscmp(buffer, L"hello worldX"), "_snprintf returned buffer %s, expected 'hello worldX'.\n", - debugstr_w(buffer)); + debugstr_wn(buffer, ARRAY_SIZE(buffer)));
wcscpy(buffer, origstring); res = p_snwprintf(buffer, lstrlenW(teststring) + 1, teststring); ok(res == lstrlenW(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenW(teststring)); ok(!wcscmp(buffer, teststring), "_snprintf returned buffer %s, expected %s.\n", - debugstr_w(buffer), debugstr_w(teststring)); + debugstr_wn(buffer, ARRAY_SIZE(buffer)), debugstr_w(teststring));
memset(buffer, 0xcc, sizeof(buffer)); res = p_snwprintf(buffer, 4, L"test"); ok(res == 4, "res = %d\n", res); - ok(!memcmp(buffer, L"test", 4 * sizeof(WCHAR)), "buf = %s\n", debugstr_w(buffer)); + ok(!memcmp(buffer, L"test", 4 * sizeof(WCHAR)), "buf = %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer))); ok(buffer[4] == 0xcccc, "buffer[4] = %x\n", buffer[4]);
memset(buffer, 0xcc, sizeof(buffer)); res = p_snwprintf(buffer, 3, L"test"); ok(res == -1, "res = %d\n", res); - ok(!memcmp(buffer, L"tes", 3 * sizeof(WCHAR)), "buf = %s\n", debugstr_w(buffer)); + ok(!memcmp(buffer, L"tes", 3 * sizeof(WCHAR)), "buf = %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer))); ok(buffer[3] == 0xcccc, "buffer[3] = %x\n", buffer[3]);
memset(buffer, 0xcc, sizeof(buffer)); res = p_snwprintf(buffer, 4, L"%s", L"test"); ok(res == 4, "res = %d\n", res); - ok(!memcmp(buffer, L"test", 4 * sizeof(WCHAR)), "buf = %s\n", debugstr_w(buffer)); + ok(!memcmp(buffer, L"test", 4 * sizeof(WCHAR)), "buf = %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer))); ok(buffer[4] == 0xcccc, "buffer[4] = %x\n", buffer[4]);
memset(buffer, 0xcc, sizeof(buffer)); res = p_snwprintf(buffer, 3, L"%s", L"test"); ok(res == -1, "res = %d\n", res); - ok(!memcmp(buffer, L"tes", 3), "buf = %s\n", debugstr_w(buffer)); + ok(!memcmp(buffer, L"tes", 3), "buf = %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer))); ok(buffer[3] == 0xcccc, "buffer[3] = %x\n", buffer[3]);
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%I64x %d", (ULONGLONG)0x1234567890, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); - ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_w(buffer)); + ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%I32x %d", 0x123456, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); - ok(!wcscmp(buffer, L"123456 1"), "got %s\n", debugstr_w(buffer)); + ok(!wcscmp(buffer, L"123456 1"), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%#x %#x", 0, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); - ok(!wcscmp(buffer, L"0 0x1"), "got %s\n", debugstr_w(buffer)); + ok(!wcscmp(buffer, L"0 0x1"), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%hx %hd", 0x123456, 987654); ok(res == lstrlenW(buffer), "wrong size %d\n", res); - ok(!wcscmp(buffer, L"3456 4614"), "got %s\n", debugstr_w(buffer)); + ok(!wcscmp(buffer, L"3456 4614"), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
if (sizeof(void *) == 8) { res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%Ix %d", (ULONG_PTR)0x1234567890, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); - ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_w(buffer)); + ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%zx %d", (ULONG_PTR)0x1234567890, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"zx 878082192")), - "got %s\n", debugstr_w(buffer)); + "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%tx %d", (ULONG_PTR)0x1234567890, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"tx 878082192")), - "got %s\n", debugstr_w(buffer)); + "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%jx %d", (ULONG_PTR)0x1234567890, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"jx 878082192")), - "got %s\n", debugstr_w(buffer)); + "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%llx %d", (ULONG_PTR)0x1234567890, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); - ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_w(buffer)); + ok(!wcscmp(buffer, L"1234567890 1"), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer))); } else { res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%Ix %d", (ULONG_PTR)0x123456, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); - ok(!wcscmp(buffer, L"123456 1"), "got %s\n", debugstr_w(buffer)); + ok(!wcscmp(buffer, L"123456 1"), "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%zx %d", (ULONG_PTR)0x123456, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); ok(!wcscmp(buffer, L"123456 1") || broken(!wcscmp(buffer, L"zx 1193046")), - "got %s\n", debugstr_w(buffer)); + "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%tx %d", (ULONG_PTR)0x123456, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); ok(!wcscmp(buffer, L"123456 1") || broken(!wcscmp(buffer, L"tx 1193046")), - "got %s\n", debugstr_w(buffer)); + "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%jx %d", 0x1234567890ull, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"jx 878082192")), - "got %s\n", debugstr_w(buffer)); + "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer)));
res = p_snwprintf(buffer, ARRAY_SIZE(buffer), L"%llx %d", 0x1234567890ull, 1); ok(res == lstrlenW(buffer), "wrong size %d\n", res); ok(!wcscmp(buffer, L"1234567890 1") || broken(!wcscmp(buffer, L"34567890 18")), /* winxp */ - "got %s\n", debugstr_w(buffer)); + "got %s\n", debugstr_wn(buffer, ARRAY_SIZE(buffer))); } }
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/setupapi/tests/devinst.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index c5c0114b2b7..3b900eeed31 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -4464,7 +4464,7 @@ static void test_driver_store(struct testsign_context *ctx) memset(dest, 0xcc, sizeof(dest)); ret = pDriverStoreFindDriverPackageA("winetest.inf", 0, 0, system_info.wProcessorArchitecture, 0, dest, &size); ok(ret == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Got %#x.\n", ret); - ok(!dest[0], "Got %s.\n", debugstr_a(dest)); + ok(!dest[0], "Got %s.\n", debugstr_an(dest, ARRAY_SIZE(dest))); todo_wine ok(!size, "Got size %lu.\n", size);
/* Windows 7 allows relative paths. Windows 8+ do not. @@ -4479,8 +4479,8 @@ static void test_driver_store(struct testsign_context *ctx) ok(!ret, "Got %#x.\n", ret); ok(size > ARRAY_SIZE(repository_dir), "Got size %lu.\n", size); ok(size == strlen(dest) + 1, "Expected size %Iu, got %lu.\n", strlen(dest) + 1, size); - ok(!memicmp(dest, repository_dir, strlen(repository_dir)), "Got path %s.\n", debugstr_a(dest)); - ok(!strcmp(dest + strlen(dest) - 13, "\winetest.inf"), "Got path %s.\n", debugstr_a(dest)); + ok(!memicmp(dest, repository_dir, strlen(repository_dir)), "Got path %s.\n", debugstr_an(dest, ARRAY_SIZE(dest))); + ok(!strcmp(dest + strlen(dest) - 13, "\winetest.inf"), "Got path %s.\n", debugstr_an(dest, ARRAY_SIZE(dest)));
strcpy(orig_dest, dest);
@@ -4489,14 +4489,14 @@ static void test_driver_store(struct testsign_context *ctx) memset(dest, 0xcc, sizeof(dest)); ret = pDriverStoreAddDriverPackageA(inf_path, 0, 0, system_info.wProcessorArchitecture, dest, &size); ok(!ret, "Got %#x.\n", ret); - ok(!strcmp(dest, orig_dest), "Expected %s, got %s.\n", debugstr_a(orig_dest), debugstr_a(dest)); + ok(!strcmp(dest, orig_dest), "Expected %s, got %s.\n", debugstr_a(orig_dest), debugstr_an(dest, ARRAY_SIZE(dest))); ok(size == strlen(dest) + 1, "Expected size %Iu, got %lu.\n", strlen(dest) + 1, size);
size = ARRAY_SIZE(dest); memset(dest, 0xcc, sizeof(dest)); ret = pDriverStoreFindDriverPackageA("winetest.inf", 0, 0, system_info.wProcessorArchitecture, 0, dest, &size); ok(!ret, "Got %#x.\n", ret); - ok(!strcmp(dest, orig_dest), "Expected %s, got %s.\n", debugstr_a(orig_dest), debugstr_a(dest)); + ok(!strcmp(dest, orig_dest), "Expected %s, got %s.\n", debugstr_a(orig_dest), debugstr_an(dest, ARRAY_SIZE(dest))); ok(size == strlen(dest) + 1, "Expected size %Iu, got %lu.\n", strlen(dest) + 1, size);
/* Test the length parameter. @@ -4507,7 +4507,7 @@ static void test_driver_store(struct testsign_context *ctx) memset(dest, 0xcc, sizeof(dest)); ret = pDriverStoreFindDriverPackageA("winetest.inf", 0, 0, system_info.wProcessorArchitecture, 0, dest, &size); ok(ret == E_INVALIDARG, "Got %#x.\n", ret); - ok(dest[0] == (char)0xcc, "Got %s.\n", debugstr_a(dest)); + ok(dest[0] == (char)0xcc, "Got %s.\n", debugstr_an(dest, ARRAY_SIZE(dest))); ok(size == MAX_PATH - 1, "Expected size %Iu, got %lu.\n", strlen(orig_dest) + 1, size);
size = 0; @@ -4582,7 +4582,7 @@ static void test_driver_store(struct testsign_context *ctx) ok(!ret || ret == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) /* Win < 8 */, "Got %#x.\n", ret); if (!ret) { - ok(!strcmp(dest, orig_dest), "Expected %s, got %s.\n", debugstr_a(orig_dest), debugstr_a(dest)); + ok(!strcmp(dest, orig_dest), "Expected %s, got %s.\n", debugstr_a(orig_dest), debugstr_an(dest, ARRAY_SIZE(dest))); ok(size == strlen(dest) + 1, "Expected size %Iu, got %lu.\n", strlen(dest) + 1, size); }
@@ -4594,7 +4594,7 @@ static void test_driver_store(struct testsign_context *ctx) memset(dest, 0xcc, sizeof(dest)); ret = pDriverStoreFindDriverPackageA("not_winetest.inf", 0, 0, system_info.wProcessorArchitecture, 0, dest, &size); ok(ret == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Got %#x.\n", ret); - ok(!dest[0], "Got %s.\n", debugstr_a(dest)); + ok(!dest[0], "Got %s.\n", debugstr_an(dest, ARRAY_SIZE(dest))); todo_wine ok(!size, "Got size %lu.\n", size);
ret = SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, set, &device);
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/user32/tests/input.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index eb548ea0924..ebd1a6e4e65 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -3824,19 +3824,19 @@ static void test_key_names(void)
memset( bufferW, 0xcc, sizeof(bufferW) ); ret = GetKeyNameTextW( lparam, bufferW, ARRAY_SIZE(bufferW)); - ok( ret > 0, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) ); - ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) ); + ok( ret > 0, "wrong len %u for %s\n", ret, wine_dbgstr_wn(bufferW, ARRAY_SIZE(bufferW)) ); + ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_wn(bufferW, ARRAY_SIZE(bufferW)) );
memset( bufferW, 0xcc, sizeof(bufferW) ); prev = ret; ret = GetKeyNameTextW( lparam, bufferW, prev ); - ok( ret == prev - 1, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) ); - ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) ); + ok( ret == prev - 1, "wrong len %u for %s\n", ret, wine_dbgstr_wn(bufferW, ARRAY_SIZE(bufferW)) ); + ok( ret == lstrlenW(bufferW), "wrong len %u for %s\n", ret, wine_dbgstr_wn(bufferW, ARRAY_SIZE(bufferW)) );
memset( bufferW, 0xcc, sizeof(bufferW) ); ret = GetKeyNameTextW( lparam, bufferW, 0 ); - ok( ret == 0, "wrong len %u for %s\n", ret, wine_dbgstr_w(bufferW) ); - ok( bufferW[0] == 0xcccc, "wrong string %s\n", wine_dbgstr_w(bufferW) ); + ok( ret == 0, "wrong len %u for %s\n", ret, wine_dbgstr_wn(bufferW, ARRAY_SIZE(bufferW)) ); + ok( bufferW[0] == 0xcccc, "wrong string %s\n", wine_dbgstr_wn(bufferW, ARRAY_SIZE(bufferW)) ); }
static void simulate_click(BOOL left, int x, int y)
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/user32/tests/win.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 8da4e11b635..1d3feaca234 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -8345,7 +8345,7 @@ static void test_gettext(void) bufW[0] = 0xcc; buf_len = InternalGetWindowText( hwnd, bufW, ARRAYSIZE(bufW) ); ok( buf_len == ARRAYSIZE("caption") - 1, "expected a nonempty window text\n" ); - ok( !lstrcmpW( bufW, L"caption" ), "got %s\n", debugstr_w(bufW) ); + ok( !lstrcmpW( bufW, L"caption" ), "got %s\n", debugstr_wn(bufW, ARRAY_SIZE(bufW)) );
g_wm_gettext_override.enabled = FALSE;
@@ -8458,7 +8458,7 @@ static void test_gettext(void) g_wm_gettext_override.dont_terminate = TRUE; buf_len = GetWindowTextW( hwnd, bufW, ARRAY_SIZE(bufW)); ok( buf_len == 4, "Unexpected text length, %d\n", buf_len ); - ok( !memcmp(bufW, textW, 4 * sizeof(WCHAR)), "Unexpected window text, %s\n", wine_dbgstr_w(bufW) ); + ok( !memcmp(bufW, textW, 4 * sizeof(WCHAR)), "Unexpected window text, %s\n", wine_dbgstr_wn(bufW, ARRAY_SIZE(bufW)) ); ok( bufW[4] == 0, "Unexpected buffer contents, %#x\n", bufW[4] ); g_wm_gettext_override.dont_terminate = FALSE;
@@ -8477,7 +8477,7 @@ static void test_gettext(void) g_wm_gettext_override.dont_terminate = TRUE; buf_len = GetWindowTextW( hwnd2, bufW, ARRAY_SIZE(bufW)); ok( buf_len == 4, "Unexpected text length, %d\n", buf_len ); - ok( !memcmp(bufW, textW, 4 * sizeof(WCHAR)), "Unexpected window text, %s\n", wine_dbgstr_w(bufW) ); + ok( !memcmp(bufW, textW, 4 * sizeof(WCHAR)), "Unexpected window text, %s\n", wine_dbgstr_wn(bufW, ARRAY_SIZE(bufW)) ); ok( bufW[4] == 0x1c1c, "Unexpected buffer contents, %#x\n", bufW[4] ); g_wm_gettext_override.dont_terminate = FALSE;
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/win32u/tests/win32u.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 8e1b56f6501..e2c97efe989 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -206,7 +206,7 @@ static void test_class(void) ok( ret == 4, "NtUserGetAtomName returned %lu\n", ret ); ok( name.Length == 0xdead, "Length = %u\n", name.Length ); ok( name.MaximumLength == sizeof(buf), "MaximumLength = %u\n", name.MaximumLength ); - ok( !wcscmp( buf, L"test" ), "buf = %s\n", debugstr_w(buf) ); + ok( !wcscmp( buf, L"test" ), "buf = %s\n", debugstr_wn(buf, ARRAY_SIZE(buf)) );
memset( buf, 0xcc, sizeof(buf) ); name.Buffer = buf; @@ -216,7 +216,7 @@ static void test_class(void) ok( ret == 3, "NtUserGetAtomName returned %lu\n", ret ); ok( name.Length == 0xdead, "Length = %u\n", name.Length ); ok( name.MaximumLength == 8, "MaximumLength = %u\n", name.MaximumLength ); - ok( !wcscmp( buf, L"tes" ), "buf = %s\n", debugstr_w(buf) ); + ok( !wcscmp( buf, L"tes" ), "buf = %s\n", debugstr_wn(buf, ARRAY_SIZE(buf)) );
memset( buf, 0xcc, sizeof(buf) ); name.Buffer = buf; @@ -234,7 +234,7 @@ static void test_class(void) ok( ret == 4, "NtUserGetClassName returned %lu\n", ret ); ok( name.Length == 0xdead, "Length = %u\n", name.Length ); ok( name.MaximumLength == sizeof(buf), "MaximumLength = %u\n", name.MaximumLength ); - ok( !wcscmp( buf, L"test" ), "buf = %s\n", debugstr_w(buf) ); + ok( !wcscmp( buf, L"test" ), "buf = %s\n", debugstr_wn(buf, ARRAY_SIZE(buf)) );
memset( buf, 0xcc, sizeof(buf) ); name.Buffer = buf; @@ -244,7 +244,7 @@ static void test_class(void) ok( ret == 3, "NtUserGetClassName returned %lu\n", ret ); ok( name.Length == 0xdead, "Length = %u\n", name.Length ); ok( name.MaximumLength == 8, "MaximumLength = %u\n", name.MaximumLength ); - ok( !wcscmp( buf, L"tes" ), "buf = %s\n", debugstr_w(buf) ); + ok( !wcscmp( buf, L"tes" ), "buf = %s\n", debugstr_wn(buf, ARRAY_SIZE(buf)) );
memset( buf, 0xcc, sizeof(buf) ); name.Buffer = buf; @@ -266,7 +266,7 @@ static void test_class(void) ret = NtUserGetAtomName( class, &name ); ok( !ret && GetLastError() == ERROR_INVALID_HANDLE, "NtUserGetAtomName returned %lx %lu\n", ret, GetLastError() ); - ok( buf[0] == 0xcccc, "buf = %s\n", debugstr_w(buf) ); + ok( buf[0] == 0xcccc, "buf = %s\n", debugstr_wn(buf, ARRAY_SIZE(buf)) );
}
Nikolay Sivov (@nsivov) commented about dlls/kernel32/tests/actctx.c:
We could instead print one char here.
Nikolay Sivov (@nsivov) commented about dlls/kernel32/tests/actctx.c:
Why would this one fail?
On Fri Jan 24 23:10:24 2025 +0000, Nikolay Sivov wrote:
Why would this one fail?
Thanks for reviewing.
I have replaced in affected functions all occourences of such `wine_dbgstr_w(buffer)` parameters.
The actual output here is as below, so really it is just line 3432.
Do you want me to limit my modifications to just lines were I get a message from ASan?
``` $ ASAN_OPTIONS="allocator_may_return_null=1:log_path="c:\asan_$(date +%Y-%m-%d_%H-%M-%S)_":halt_on_error=0" wine dlls/kernel32/tests/x86_64-windows/kernel32_test.exe actctx $ cat $WINEPREFIX/drive_c/asan_2025-01-25_00-40-09_.296 ================================================================= ==296==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffffe1ffac0 at pc 0x00014000bbf1 bp 0x7ffffe1ff6e0 sp 0x7ffffe1ff728 READ of size 2 at 0x7ffffe1ffac0 thread T0 #0 0x00014000bbf0 in wine_dbgstr_wn Z:...\wine\include\wine\debug.h:263 #1 0x00014000ba0e in wine_dbgstr_w Z:...\wine\include\wine\debug.h:306 #2 0x00014000757f in test_settings Z:...\wine\dlls\kernel32\tests\actctx.c:3432 #3 0x00014000118a in func_actctx Z:...\wine\dlls\kernel32\tests\actctx.c:4436 #4 0x0001401f492e in run_test+0xae (Z:...\wine-build\build-asan-pe\64\obj\dlls\kernel32\tests\x86_64-windows\kernel32_test.exe+0x1401f492e) #5 0x0001401f4471 in main+0x471 (Z:...\wine-build\build-asan-pe\64\obj\dlls\kernel32\tests\x86_64-windows\kernel32_test.exe+0x1401f4471) #6 0x0001401f5de3 in mainCRTStartup Z:...\wine\dlls\msvcrt\crt_main.c:58 #7 0x6fffffc455ee in BaseThreadInitThunk Z:...\wine\dlls\kernel32\thread.c:61 #8 0x6fffffdcab0a (C:\windows\system32\ntdll.dll+0x17004ab0a)
Address 0x7ffffe1ffac0 is located in stack of thread T0 at offset 192 in frame #0 0x00014000710f in test_settings Z:...\wine\dlls\kernel32\tests\actctx.c:3389
This frame has 2 object(s): [32, 192) 'buffer' (line 3396) <== Memory access at offset 192 overflows this variable [256, 264) 'size' (line 3397) HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp, SEH and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow Z:...\wine\include\wine\debug.h:263 in wine_dbgstr_wn Shadow bytes around the buggy address: 0x7ffffe1ff800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7ffffe1ff880: 00 00 00 00 00 04 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 0x7ffffe1ff900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7ffffe1ff980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7ffffe1ffa00: f1 f1 f1 f1 00 00 00 00 00 00 00 00 00 00 00 00 =>0x7ffffe1ffa80: 00 00 00 00 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2 0x7ffffe1ffb00: 00 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 0x7ffffe1ffb80: 00 00 00 00 f1 f1 f1 f1 00 f3 f3 f3 00 00 00 00 0x7ffffe1ffc00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7ffffe1ffc80: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 f8 f8 f8 f8 0x7ffffe1ffd00: f8 f8 f8 f8 f3 f3 f3 f3 00 00 00 00 00 00 00 00 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 ==296==ABORTING ```
On Fri Jan 24 23:49:37 2025 +0000, Bernhard Übelacker wrote:
I don't know what's the best option here. Does this overrun happen in normal builds too, without ASan? If it's a side effect of using ASan somehow, then changes are here only to suppress this side effect.
Why would this one fail?
It didn't fail. As Bernhard said above, the MR collectively modifies all occurences of `wine_dbgstr_w` in functions that had at least one ASan failure.
IIUC these are only problematic when the test fails *and* when the failure leaves the buffer unchanged. Both of which are unlikely and not supposed to happen.
Imo having to use the sized version is annoying, and the asan warning arguably a false positive (it's theoretically possible, but not a problem in practice). Another, les intrusive option would be to zero initialize the buffers, or always add a 0 at the end instead.
Thanks for all your input, as Nikolay asked if this happens in a normal build, I tried [this test](https://testbot.winehq.org/JobDetails.pl?Key=151060&f101=wow64.report#k1...) on the testbot. It creates a buffer on a page boundary and switches the latter page to PAGE_NOACCESS.
If I interpret the output right it means overrunning in `wine_dbgstr_w` would be save as it then returns just `(invalid)`. This seems to originate from a check with `IsBadStringPtrA`.
Unfortunately this makes it harder to show if a succeeding `ok` gets the `wine_dbgstr_w` executed before the condition is evaluated. Therefore I added the lines with `strlen`, and that one seems to already crash on the succeeding `ok`.
However, as this creates no problem in regular builds I guess another option would be to simply ignore the reading overrun `wine_dbgstr_an`/`wine_dbgstr_wn` by disabling ASan just for these functions.
Thanks again for your help, I will do some tests and report back.
it looks to me that the ASan failures show places where the assumptions on buffers made for the test in` ok()` don't match the assumptions made for the passing the arguments to `wine_dbgstr*()`
by assumptions:
* is the buffer always 0 terminated? * do we care the first N bytes of the buffer (even if the size of the buffer is larger)
eg, if test use `strcmp/wcscmp` then using `wine_dbgstr_[aw]` should be "fine" ("fine" doesn't mean no overrun, but meaning same overrun behavior in test and arguments (or even more protected in `wine_dbgstr` because of the `IsBad`... call) : IOW, if the test fails in ASan, the whole code of the test should really be fixed)
most the failures I see are because:
* test just tests first byte (likely trying to test that the buffer is untouched) => we should only print first byte as Nikolay suggested (or even no argument at all as the meaning of the test is the buffer has been tempered) * test uses `memcmp, strncmp`.... (implying that the buffers could be not 0 terminated), in that case the` wine_dbgstr_[aw]n` should be used, but with the same length as the ones used in the comparison not the full buffer size
By [removing instrumentation from wine_dbgstr_[aw]n](https://gitlab.winehq.org/bernhardu/wine/-/commit/5202d12e92b0499d66160b48d5...) I received no more such unwanted positives.
As far as currently I just still one issue with a lstrlenW which I think this merge request https://gitlab.winehq.org/wine/wine/-/merge_requests/7201 would be a better fix.
Therefore it looks like this merge request ended in smoke and I am going to close it. Thanks for all your help and sorry for the noise.
This merge request was closed by Bernhard Übelacker.