The pointer in tmplocale gets freed in the second setlocale call. Therefore ASan triggers when trying to restore the locale the the already freed pointer in tmplocale in the third call to setlocale.
This appeared with a notepad.exe built with (a yet patched) llvm-mingw with ASan enabled, when opening the Printer Setup dialog.
The stack traces seem to have utilized an in the wineprefix installed LLVM/llvm-symbolizer.exe.
``` wine64 notepad_asan.exe
================================================================= ==300==ERROR: AddressSanitizer: heap-use-after-free on address 0x7eeab5c60290 at pc 0x6ffffa80279f bp 0x7ffffe1fb570 sp 0x7ffffe1fb5b0 READ of size 2 at 0x7eeab5c60290 thread T0 0130:fixme:dbghelp:elf_search_auxv can't find symbol in module #0 0x6ffffa80279e in strchr+0x28e (C:\x86_64\libclang_rt.asan_dynamic-x86_64.dll+0x18004279e) #1 0x6ffffeb1666c in locale_to_sname Z:\home\bernhard\wine\dlls\msvcrt\locale.c:351 #2 0x6ffffeb16ce5 in create_locinfo Z:\home\bernhard\wine\dlls\msvcrt\locale.c:1357 #3 0x6ffffeb1a170 in setlocale Z:\home\bernhard\wine\dlls\msvcrt\locale.c:2054 #4 0x6ffffa1bf8c9 in PSDRV_ParsePPD Z:\home\bernhard\wine\dlls\wineps.drv\ppd.c:890 #5 0x6ffffa1bc0b7 in PSDRV_FindPrinterInfo Z:\home\bernhard\wine\dlls\wineps.drv\init.c:575 #6 0x6ffffa1b66b1 in DrvDocumentPropertySheets Z:\home\bernhard\wine\dlls\wineps.drv\driver.c:491 #7 0x6ffffc60b314 in DocumentPropertiesW Z:\home\bernhard\wine\dlls\winspool.drv\info.c:1854 #8 0x6ffffc611f97 in OpenPrinter2W Z:\home\bernhard\wine\dlls\winspool.drv\info.c:2057 #9 0x6ffffd666153 in PRINTDLG_ChangePrinterW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:1298 #10 0x6ffffd66786d in PRINTDLG_WMInitDialogW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:1660 #11 0x6ffffd667987 in PrintDlgProcW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:2126 #12 0x6ffffdc08d48 in call_dialog_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:129 #13 0x6ffffdc0b13b in WINPROC_CallDlgProcW Z:\home\bernhard\wine\dlls\user32\winproc.c:948 #14 0x6ffffdbcf528 in USER_DefDlgProc Z:\home\bernhard\wine\dlls\user32\defdlg.c:372 #15 0x6ffffdbcf7b4 in DefDlgProcW Z:\home\bernhard\wine\dlls\user32\defdlg.c:438 #16 0x6ffffdc08c2a in call_window_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:108 #17 0x6ffffdc0ac43 in dispatch_win_proc_params Z:\home\bernhard\wine\dlls\user32\winproc.c:725 #18 0x6ffffdbf179c in dispatch_send_message Z:\home\bernhard\wine\dlls\user32\message.c:580 #19 0x6ffffdbf32ee in SendMessageW Z:\home\bernhard\wine\dlls\user32\message.c:599 #20 0x6ffffdbd2d1a in DIALOG_CreateIndirect Z:\home\bernhard\wine\dlls\user32\dialog.c:676 #21 0x6ffffdbd4d1c in DialogBoxIndirectParamW Z:\home\bernhard\wine\dlls\user32\dialog.c:899 #22 0x6ffffd6692a7 in PrintDlgW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:2546 #23 0x000140007f9b in DIALOG_FilePrinterSetup Z:\home\bernhard\wine\programs\notepad\dialog.c:1019 #24 0x00014000e118 in NOTEPAD_WndProc Z:\home\bernhard\wine\programs\notepad\main.c:640 #25 0x6ffffdc08c2a in call_window_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:108 #26 0x6ffffdc0ac43 in dispatch_win_proc_params Z:\home\bernhard\wine\dlls\user32\winproc.c:725 #27 0x6ffffdbf1850 in dispatch_message Z:\home\bernhard\wine\dlls\user32\message.c:854 #28 0x6ffffdbf3afc in DispatchMessageW Z:\home\bernhard\wine\dlls\user32\message.c:940 #29 0x00014000c4ef in WinMain Z:\home\bernhard\wine\programs\notepad\main.c:888 #30 0x00014000ea3e in main+0x20e (C:\x86_64\notepad.exe_asan.exe+0x14000ea3e) #31 0x00014000e75a in mainCRTStartup Z:\home\bernhard\wine\dlls\msvcrt\crt_main.c:58 #32 0x6fffffa98d58 in BaseThreadInitThunk Z:\home\bernhard\wine\dlls\kernel32\thread.c:61 #33 0x6fffffc95afa (C:\windows\system32\ntdll.dll+0x170055afa)
0x7eeab5c60290 is located 0 bytes inside of 2-byte region [0x7eeab5c60290,0x7eeab5c60292) freed by thread T0 here: #0 0x6ffffa809ff1 in free+0x81 (C:\x86_64\libclang_rt.asan_dynamic-x86_64.dll+0x180049ff1) #1 0x6ffffeb1563c in free_locinfo Z:\home\bernhard\wine\dlls\msvcrt\locale.c:1071 #2 0x6ffffeb1591a in update_thread_locale Z:\home\bernhard\wine\dlls\msvcrt\locale.c:611 #3 0x6ffffeb1a301 in setlocale Z:\home\bernhard\wine\dlls\msvcrt\locale.c:2085 #4 0x6ffffa1bf890 in PSDRV_ParsePPD Z:\home\bernhard\wine\dlls\wineps.drv\ppd.c:887 #5 0x6ffffa1bc0b7 in PSDRV_FindPrinterInfo Z:\home\bernhard\wine\dlls\wineps.drv\init.c:575 #6 0x6ffffa1b66b1 in DrvDocumentPropertySheets Z:\home\bernhard\wine\dlls\wineps.drv\driver.c:491 #7 0x6ffffc60b314 in DocumentPropertiesW Z:\home\bernhard\wine\dlls\winspool.drv\info.c:1854 #8 0x6ffffc611f97 in OpenPrinter2W Z:\home\bernhard\wine\dlls\winspool.drv\info.c:2057 #9 0x6ffffd666153 in PRINTDLG_ChangePrinterW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:1298 #10 0x6ffffd66786d in PRINTDLG_WMInitDialogW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:1660 #11 0x6ffffd667987 in PrintDlgProcW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:2126 #12 0x6ffffdc08d48 in call_dialog_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:129 #13 0x6ffffdc0b13b in WINPROC_CallDlgProcW Z:\home\bernhard\wine\dlls\user32\winproc.c:948 #14 0x6ffffdbcf528 in USER_DefDlgProc Z:\home\bernhard\wine\dlls\user32\defdlg.c:372 #15 0x6ffffdbcf7b4 in DefDlgProcW Z:\home\bernhard\wine\dlls\user32\defdlg.c:438 #16 0x6ffffdc08c2a in call_window_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:108 #17 0x6ffffdc0ac43 in dispatch_win_proc_params Z:\home\bernhard\wine\dlls\user32\winproc.c:725 #18 0x6ffffdbf179c in dispatch_send_message Z:\home\bernhard\wine\dlls\user32\message.c:580 #19 0x6ffffdbf32ee in SendMessageW Z:\home\bernhard\wine\dlls\user32\message.c:599 #20 0x6ffffdbd2d1a in DIALOG_CreateIndirect Z:\home\bernhard\wine\dlls\user32\dialog.c:676 #21 0x6ffffdbd4d1c in DialogBoxIndirectParamW Z:\home\bernhard\wine\dlls\user32\dialog.c:899 #22 0x6ffffd6692a7 in PrintDlgW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:2546 #23 0x000140007f9b in DIALOG_FilePrinterSetup Z:\home\bernhard\wine\programs\notepad\dialog.c:1019 #24 0x00014000e118 in NOTEPAD_WndProc Z:\home\bernhard\wine\programs\notepad\main.c:640 #25 0x6ffffdc08c2a in call_window_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:108 #26 0x6ffffdc0ac43 in dispatch_win_proc_params Z:\home\bernhard\wine\dlls\user32\winproc.c:725 #27 0x6ffffdbf1850 in dispatch_message Z:\home\bernhard\wine\dlls\user32\message.c:854
previously allocated by thread T0 here: #0 0x6ffffa80a111 in malloc+0x81 (C:\x86_64\libclang_rt.asan_dynamic-x86_64.dll+0x18004a111) #1 0x6ffffeb154f9 in init_category_name Z:\home\bernhard\wine\dlls\msvcrt\locale.c:474 #2 0x6ffffeb18ad9 in create_locinfo Z:\home\bernhard\wine\dlls\msvcrt\locale.c:1930 #3 0x6ffffeb1a170 in setlocale Z:\home\bernhard\wine\dlls\msvcrt\locale.c:2054 #4 0x6ffffa1bf8c9 in PSDRV_ParsePPD Z:\home\bernhard\wine\dlls\wineps.drv\ppd.c:890 #5 0x6ffffa1bc0b7 in PSDRV_FindPrinterInfo Z:\home\bernhard\wine\dlls\wineps.drv\init.c:575 #6 0x6ffffa1b66b1 in DrvDocumentPropertySheets Z:\home\bernhard\wine\dlls\wineps.drv\driver.c:491 #7 0x6ffffc60b314 in DocumentPropertiesW Z:\home\bernhard\wine\dlls\winspool.drv\info.c:1854 #8 0x6ffffc611f97 in OpenPrinter2W Z:\home\bernhard\wine\dlls\winspool.drv\info.c:2057 #9 0x6ffffd666153 in PRINTDLG_ChangePrinterW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:1298 #10 0x6ffffd66786d in PRINTDLG_WMInitDialogW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:1660 #11 0x6ffffd667987 in PrintDlgProcW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:2126 #12 0x6ffffdc08d48 in call_dialog_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:129 #13 0x6ffffdc0b13b in WINPROC_CallDlgProcW Z:\home\bernhard\wine\dlls\user32\winproc.c:948 #14 0x6ffffdbcf528 in USER_DefDlgProc Z:\home\bernhard\wine\dlls\user32\defdlg.c:372 #15 0x6ffffdbcf7b4 in DefDlgProcW Z:\home\bernhard\wine\dlls\user32\defdlg.c:438 #16 0x6ffffdc08c2a in call_window_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:108 #17 0x6ffffdc0ac43 in dispatch_win_proc_params Z:\home\bernhard\wine\dlls\user32\winproc.c:725 #18 0x6ffffdbf179c in dispatch_send_message Z:\home\bernhard\wine\dlls\user32\message.c:580 #19 0x6ffffdbf32ee in SendMessageW Z:\home\bernhard\wine\dlls\user32\message.c:599 #20 0x6ffffdbd2d1a in DIALOG_CreateIndirect Z:\home\bernhard\wine\dlls\user32\dialog.c:676 #21 0x6ffffdbd4d1c in DialogBoxIndirectParamW Z:\home\bernhard\wine\dlls\user32\dialog.c:899 #22 0x6ffffd6692a7 in PrintDlgW Z:\home\bernhard\wine\dlls\comdlg32\printdlg.c:2546 #23 0x000140007f9b in DIALOG_FilePrinterSetup Z:\home\bernhard\wine\programs\notepad\dialog.c:1019 #24 0x00014000e118 in NOTEPAD_WndProc Z:\home\bernhard\wine\programs\notepad\main.c:640 #25 0x6ffffdc08c2a in call_window_proc Z:\home\bernhard\wine\dlls\user32\winproc.c:108 #26 0x6ffffdc0ac43 in dispatch_win_proc_params Z:\home\bernhard\wine\dlls\user32\winproc.c:725 #27 0x6ffffdbf1850 in dispatch_message Z:\home\bernhard\wine\dlls\user32\message.c:854
SUMMARY: AddressSanitizer: heap-use-after-free Z:\home\bernhard\wine\dlls\msvcrt\locale.c:351 in locale_to_sname Shadow bytes around the buggy address: 0x7eeab5c60000: fa fa 00 00 fa fa 00 06 fa fa 00 fa fa fa 00 00 0x7eeab5c60080: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x7eeab5c60100: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x7eeab5c60180: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa 0x7eeab5c60200: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa =>0x7eeab5c60280: fa fa[fd]fa fa fa fd fa fa fa fd fa fa fa fd fa 0x7eeab5c60300: fa fa 02 fa fa fa 04 fa fa fa 02 fa fa fa 04 fa 0x7eeab5c60380: fa fa 02 fa fa fa 04 fa fa fa 02 fa fa fa 04 fa 0x7eeab5c60400: fa fa 02 fa fa fa 04 fa fa fa 00 fa fa fa fd fd 0x7eeab5c60480: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x7eeab5c60500: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 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 ==300==ABORTING ```
-- v4: wineps.drv: Use locale aware variants _sprintf_l and _sscanf_l. (ASan) stdio.h: Add ucrt _sprintf_l declaration.
From: Bernhard Übelacker bernhardu@mailbox.org
--- include/msvcrt/stdio.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/include/msvcrt/stdio.h b/include/msvcrt/stdio.h index 8c75930322e..1e1d28f3f70 100644 --- a/include/msvcrt/stdio.h +++ b/include/msvcrt/stdio.h @@ -326,6 +326,19 @@ static inline int __cdecl printf_s(const char *format, ...) return ret; }
+static inline int __cdecl _sprintf_l(char *buffer, const char *format, _locale_t locale, ...) __WINE_CRT_PRINTF_ATTR(2, 4); +static inline int __cdecl _sprintf_l(char *buffer, const char *format, _locale_t locale, ...) +{ + int ret; + va_list args; + + va_start(args, locale); + ret = __stdio_common_vsprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, + buffer, -1, format, locale, args); + va_end(args); + return ret < 0 ? -1 : ret; +} + static inline int __cdecl sscanf(const char *buffer, const char *format, ...) __WINE_CRT_SCANF_ATTR(2, 3); static inline int __cdecl sscanf(const char *buffer, const char *format, ...) { @@ -519,6 +532,7 @@ static inline int __cdecl sprintf(char *buffer, const char *format, ...) _ACRTIMP int __cdecl snprintf(char*,size_t,const char*,...) __WINE_CRT_PRINTF_ATTR(3, 4); _ACRTIMP int __cdecl _snprintf(char*,size_t,const char*,...) __WINE_CRT_PRINTF_ATTR(3, 4); _ACRTIMP int __cdecl sprintf(char*,const char*,...) __WINE_CRT_PRINTF_ATTR(2, 3); +_ACRTIMP int __cdecl _sprintf_l(char*,const char*,_locale_t,...) __WINE_CRT_PRINTF_ATTR(2, 4);
#endif /* !_NO_CRT_STDIO_INLINE */
From: Bernhard Übelacker bernhardu@mailbox.org
--- dlls/wineps.drv/init.c | 6 +++++- dlls/wineps.drv/ppd.c | 9 ++------- dlls/wineps.drv/ps.c | 17 ++++------------- dlls/wineps.drv/psdrv.h | 8 +------- dlls/wineps.drv/type42.c | 8 +++----- 5 files changed, 15 insertions(+), 33 deletions(-)
diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c index ec4dc174cf9..7128177c94f 100644 --- a/dlls/wineps.drv/init.c +++ b/dlls/wineps.drv/init.c @@ -21,6 +21,7 @@
#include <stdarg.h> #include <string.h> +#include <locale.h>
#include "windef.h" #include "winbase.h" @@ -87,6 +88,7 @@ static const PSDRV_DEVMODE DefaultDevmode =
HINSTANCE PSDRV_hInstance = 0; HANDLE PSDRV_Heap = 0; +_locale_t c_locale;
static BOOL import_ntf_from_reg(void) { @@ -294,6 +296,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { PSDRV_hInstance = hinst; DisableThreadLibraryCalls(hinst); + c_locale = _create_locale( LC_ALL, "C" );
if (__wine_init_unix_call()) return FALSE; @@ -319,7 +322,8 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) case DLL_PROCESS_DETACH: if (reserved) break; WINE_UNIX_CALL(unix_free_printer_info, NULL); - HeapDestroy( PSDRV_Heap ); + _free_locale( c_locale ); + HeapDestroy( PSDRV_Heap ); break; }
diff --git a/dlls/wineps.drv/ppd.c b/dlls/wineps.drv/ppd.c index d116f8ebbc0..a1f66cd27b5 100644 --- a/dlls/wineps.drv/ppd.c +++ b/dlls/wineps.drv/ppd.c @@ -884,10 +884,7 @@ PPD *PSDRV_ParsePPD( const WCHAR *fname, HANDLE printer ) #define PIA page->ImageableArea if(!PIA) { PIA = HeapAlloc( PSDRV_Heap, 0, sizeof(*PIA) ); - push_lc_numeric("C"); - sscanf(tuple.value, "%f%f%f%f", &PIA->llx, &PIA->lly, - &PIA->urx, &PIA->ury); - pop_lc_numeric(); + _sscanf_l(tuple.value, "%f%f%f%f", c_locale, &PIA->llx, &PIA->lly, &PIA->urx, &PIA->ury); } #undef PIA } @@ -908,9 +905,7 @@ PPD *PSDRV_ParsePPD( const WCHAR *fname, HANDLE printer ) #define PD page->PaperDimension if(!PD) { PD = HeapAlloc( PSDRV_Heap, 0, sizeof(*PD) ); - push_lc_numeric("C"); - sscanf(tuple.value, "%f%f", &PD->x, &PD->y); - pop_lc_numeric(); + _sscanf_l(tuple.value, "%f%f", c_locale, &PD->x, &PD->y); } #undef PD } diff --git a/dlls/wineps.drv/ps.c b/dlls/wineps.drv/ps.c index 8e52a97867a..7a8feeaedb8 100644 --- a/dlls/wineps.drv/ps.c +++ b/dlls/wineps.drv/ps.c @@ -625,9 +625,7 @@ BOOL PSDRV_WriteArc(print_ctx *ctx, INT x, INT y, INT w, INT h, double ang1,
/* Make angles -ve and swap order because we're working with an upside down y-axis */ - push_lc_numeric("C"); - sprintf(buf, psarc, x, y, w, h, -ang2, -ang1); - pop_lc_numeric(); + _sprintf_l(buf, psarc, c_locale, x, y, w, h, -ang2, -ang1); return PSDRV_WriteSpool(ctx, buf, strlen(buf)); }
@@ -678,16 +676,11 @@ BOOL PSDRV_WriteSetColor(print_ctx *ctx, PSCOLOR *color)
switch(color->type) { case PSCOLOR_RGB: - push_lc_numeric("C"); - sprintf(buf, pssetrgbcolor, color->value.rgb.r, color->value.rgb.g, - color->value.rgb.b); - pop_lc_numeric(); + _sprintf_l(buf, pssetrgbcolor, c_locale, color->value.rgb.r, color->value.rgb.g, color->value.rgb.b); return PSDRV_WriteSpool(ctx, buf, strlen(buf));
case PSCOLOR_GRAY: - push_lc_numeric("C"); - sprintf(buf, pssetgray, color->value.gray.i); - pop_lc_numeric(); + _sprintf_l(buf, pssetgray, c_locale, color->value.gray.i); return PSDRV_WriteSpool(ctx, buf, strlen(buf));
default: @@ -786,9 +779,7 @@ BOOL PSDRV_WriteRotate(print_ctx *ctx, float ang) { char buf[256];
- push_lc_numeric("C"); - sprintf(buf, psrotate, ang); - pop_lc_numeric(); + _sprintf_l(buf, psrotate, c_locale, ang); return PSDRV_WriteSpool(ctx, buf, strlen(buf)); }
diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h index 2c4703de942..c69b2994479 100644 --- a/dlls/wineps.drv/psdrv.h +++ b/dlls/wineps.drv/psdrv.h @@ -544,13 +544,7 @@ extern DWORD ASCII85_encode(BYTE *in_buf, DWORD len, BYTE *out_buf); extern void passthrough_enter(print_ctx *ctx); extern void passthrough_leave(print_ctx *ctx);
-#define push_lc_numeric(x) do { \ - const char *tmplocale = setlocale(LC_NUMERIC,NULL); \ - setlocale(LC_NUMERIC,x); - -#define pop_lc_numeric() \ - setlocale(LC_NUMERIC,tmplocale); \ -} while (0) +extern _locale_t c_locale;
static inline WCHAR *strdupW( const WCHAR *str ) { diff --git a/dlls/wineps.drv/type42.c b/dlls/wineps.drv/type42.c index 0867881b68e..4f598962b73 100644 --- a/dlls/wineps.drv/type42.c +++ b/dlls/wineps.drv/type42.c @@ -203,11 +203,9 @@ TYPE42 *T42_download_header(print_ctx *ctx, char *ps_name, buf = HeapAlloc(GetProcessHeap(), 0, sizeof(start) + strlen(ps_name) + 100);
- push_lc_numeric("C"); - sprintf(buf, start, ps_name, - (float)bbox->left / emsize, (float)bbox->bottom / emsize, - (float)bbox->right / emsize, (float)bbox->top / emsize); - pop_lc_numeric(); + _sprintf_l(buf, start, c_locale, ps_name, + (float)bbox->left / emsize, (float)bbox->bottom / emsize, + (float)bbox->right / emsize, (float)bbox->top / emsize);
PSDRV_WriteSpool(ctx, buf, strlen(buf));
This merge request was approved by Huw Davies.