From 11e7024c52fe4ded7ac5790d83335012ef31137f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= Date: Sat, 9 Nov 2024 00:13:03 +0100 Subject: [PATCH 1/2] stdio.h: Add ucrt _sprintf_l declaration. --- 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 481ddf9798e3c0fcd5055e9514f5bd7ed2f8d506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= Date: Tue, 5 Nov 2024 17:40:00 +0100 Subject: [PATCH 2/2] wineps.drv: Use locale aware variants _sprintf_l and _sscanf_l. (ASan) Currently are the macros push_lc_numeric/pop_lc_numeric in place to temporary switch locale for sprintf and sscanf calls. This macros retrieve current locale, save it to a temporary variable "tmplocale", in between is the call to sprintf or sscanf, and restore the old locale from the temproary variable. But in the second setlocale call the pointer in tmplocale gets freed. Therefore ASan gets triggered in the third setlocale call when it attempts to read the already freed memory. This patch avoids this by removing this switching altogether. --- dlls/wineps.drv/init.c | 4 ++++ 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, 14 insertions(+), 32 deletions(-) diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c index ec4dc174cf9..2893c92d30f 100644 --- a/dlls/wineps.drv/init.c +++ b/dlls/wineps.drv/init.c @@ -21,6 +21,7 @@ #include #include +#include #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,6 +322,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) case DLL_PROCESS_DETACH: if (reserved) break; WINE_UNIX_CALL(unix_free_printer_info, NULL); + _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));