Signed-off-by: Martin Storsjo martin@martin.st --- This is an old patch that I happened to have lying around; don't remember much of the details of it, but if it applies and still works, I guess it'd be worthwhile. --- dlls/msvcrt/wcs.c | 8 ++++++-- dlls/ucrtbase/tests/printf.c | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c index 17d06eed3c..f751d658ef 100644 --- a/dlls/msvcrt/wcs.c +++ b/dlls/msvcrt/wcs.c @@ -744,7 +744,9 @@ int CDECL __stdio_common_vsprintf( unsigned __int64 options, char *str, MSVCRT_s return ret>len ? -1 : ret; if(ret>=len) { if(len) str[len-1] = 0; - return (options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) ? ret : -2; + if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) + return ret; + return len > 0 ? -2 : -1; } return ret; } @@ -1284,7 +1286,9 @@ int CDECL MSVCRT__stdio_common_vswprintf( unsigned __int64 options, return ret>len ? -1 : ret; if(ret>=len) { if(len) str[len-1] = 0; - return (options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) ? ret : -2; + if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) + return ret; + return len > 0 ? -2 : -1; } return ret; } diff --git a/dlls/ucrtbase/tests/printf.c b/dlls/ucrtbase/tests/printf.c index 8cacbbb79a..3b48e08b10 100644 --- a/dlls/ucrtbase/tests/printf.c +++ b/dlls/ucrtbase/tests/printf.c @@ -144,6 +144,18 @@ static void test_snprintf (void) "Failure to snprintf to NULL\n"); ok (vsprintf_wrapper (0, NULL, 0, "abcd") == 4, "Failure to snprintf to NULL\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, "abcd") == 4, + "Failure to snprintf to zero length buffer\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, "abcd") == -1, + "Failure to snprintf to zero length buffer\n"); + ok (vsprintf_wrapper (0, buffer, 0, "abcd") == -1, + "Failure to snprintf to zero length buffer\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, "") == 0, + "Failure to snprintf a zero length string to a zero length buffer\n"); + ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, "") == 0, + "Failure to snprintf a zero length string to a zero length buffer\n"); + ok (vsprintf_wrapper (0, buffer, 0, "") == -1, + "Failure to snprintf a zero length string to a zero length buffer\n"); }
static int WINAPIV vswprintf_wrapper(unsigned __int64 options, wchar_t *str, @@ -163,6 +175,7 @@ static void test_swprintf (void) const wchar_t str_justfit[] = {'j','u','s','t','f','i','t',0}; const wchar_t str_justfits[] = {'j','u','s','t','f','i','t','s',0}; const wchar_t str_muchlonger[] = {'m','u','c','h','l','o','n','g','e','r',0}; + const wchar_t str_empty[] = {0}; const wchar_t *tests[] = {str_short, str_justfit, str_justfits, str_muchlonger};
wchar_t buffer[8]; @@ -225,6 +238,18 @@ static void test_swprintf (void) "Failure to swprintf to NULL\n"); ok (vswprintf_wrapper (0, NULL, 0, str_short) == 5, "Failure to swprintf to NULL\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, str_short) == 5, + "Failure to swprintf to a zero length buffer\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, str_short) == -1, + "Failure to swprintf to a zero length buffer\n"); + ok (vswprintf_wrapper (0, buffer, 0, str_short) == -1, + "Failure to swprintf to a zero length buffer\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, 0, str_empty) == 0, + "Failure to swprintf a zero length string to a zero length buffer\n"); + ok (vswprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, 0, str_empty) == 0, + "Failure to swprintf a zero length string to a zero length buffer\n"); + ok (vswprintf_wrapper (0, buffer, 0, str_empty) == -1, + "Failure to swprintf a zero length string to a zero length buffer\n"); }
static int WINAPIV vfprintf_wrapper(FILE *file,
Signed-off-by: Martin Storsjo martin@martin.st --- This is an old patch that I happened to have lying around; don't remember much of the details of it, but if it applies and still works, I guess it'd be worthwhile. --- dlls/ucrtbase/tests/printf.c | 93 +++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 45 deletions(-)
diff --git a/dlls/ucrtbase/tests/printf.c b/dlls/ucrtbase/tests/printf.c index 3b48e08b10..7f409dd58c 100644 --- a/dlls/ucrtbase/tests/printf.c +++ b/dlls/ucrtbase/tests/printf.c @@ -90,52 +90,55 @@ static int WINAPIV vsprintf_wrapper(unsigned __int64 options, char *str,
static void test_snprintf (void) { - const char *tests[] = {"short", "justfit", "justfits", "muchlonger"}; + const char *tests[] = {"short", "justfit", "justfits", "muchlonger", "", "1"}; char buffer[8]; - const int bufsiz = sizeof buffer; - unsigned int i; - - /* Legacy _snprintf style termination */ - for (i = 0; i < ARRAY_SIZE(tests); i++) { - const char *fmt = tests[i]; - const int expect = strlen(fmt) > bufsiz ? -1 : strlen(fmt); - const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, bufsiz, fmt); - const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1); - - ok (n == expect, ""%s": expected %d, returned %d\n", - fmt, expect, n); - ok (!memcmp (fmt, buffer, valid), - ""%s": rendered "%.*s"\n", fmt, valid, buffer); - } - - /* C99 snprintf style termination */ - for (i = 0; i < ARRAY_SIZE(tests); i++) { - const char *fmt = tests[i]; - const int expect = strlen(fmt); - const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, bufsiz, fmt); - const int valid = n >= bufsiz ? bufsiz - 1 : n < 0 ? 0 : n; - - ok (n == expect, ""%s": expected %d, returned %d\n", - fmt, expect, n); - ok (!memcmp (fmt, buffer, valid), - ""%s": rendered "%.*s"\n", fmt, valid, buffer); - ok (buffer[valid] == '\0', - ""%s": Missing null termination (ret %d) - is %d\n", fmt, n, buffer[valid]); - } - - /* swprintf style termination */ - for (i = 0; i < ARRAY_SIZE(tests); i++) { - const char *fmt = tests[i]; - const int expect = strlen(fmt) >= bufsiz ? -2 : strlen(fmt); - const int n = vsprintf_wrapper (0, buffer, bufsiz, fmt); - const int valid = n < 0 ? bufsiz - 1 : n; - - ok (n == expect, ""%s": expected %d, returned %d\n", - fmt, expect, n); - ok (!memcmp (fmt, buffer, valid), - ""%s": rendered "%.*s"\n", fmt, valid, buffer); - ok (buffer[valid] == '\0', - ""%s": Missing null termination (ret %d) - is %d\n", fmt, n, buffer[valid]); + int bufsizes[] = { 0, 1, sizeof buffer }; + unsigned int i, j; + + for (j = 0; j < sizeof bufsizes / sizeof bufsizes[0]; j++) { + const int bufsiz = bufsizes[j]; + /* Legacy _snprintf style termination */ + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const char *fmt = tests[i]; + const int expect = strlen(fmt) > bufsiz ? -1 : strlen(fmt); + const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION, buffer, bufsiz, fmt); + const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1); + + ok (n == expect, ""%s": expected %d, returned %d\n", + fmt, expect, n); + ok (!memcmp (fmt, buffer, valid), + ""%s": rendered "%.*s"\n", fmt, valid, buffer); + } + + /* C99 snprintf style termination */ + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const char *fmt = tests[i]; + const int expect = strlen(fmt); + const int n = vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, buffer, bufsiz, fmt); + const int valid = n >= bufsiz ? (bufsiz > 0 ? bufsiz - 1 : 0) : n < 0 ? 0 : n; + + ok (n == expect, ""%s": expected %d, returned %d\n", + fmt, expect, n); + ok (!memcmp (fmt, buffer, valid), + ""%s": rendered "%.*s" bufsiz %d\n", fmt, valid, buffer, bufsiz); + ok (bufsiz == 0 || buffer[valid] == '\0', + ""%s": Missing null termination (ret %d) - is %d (bufsiz %d)\n", fmt, n, buffer[valid], bufsiz); + } + + /* swprintf style termination */ + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const char *fmt = tests[i]; + const int expect = strlen(fmt) >= bufsiz ? bufsiz > 0 ? -2 : -1 : strlen(fmt); + const int n = vsprintf_wrapper (0, buffer, bufsiz, fmt); + const int valid = n < 0 ? bufsiz > 0 ? bufsiz - 1 : 0 : n; + + ok (n == expect, ""%s": expected %d, returned %d\n", + fmt, expect, n); + ok (!memcmp (fmt, buffer, valid), + ""%s": rendered "%.*s" bufsiz %d\n", fmt, valid, buffer, bufsiz); + ok (bufsiz == 0 || buffer[valid] == '\0', + ""%s": Missing null termination (ret %d) - is %d\n", fmt, n, buffer[valid]); + } }
ok (vsprintf_wrapper (_CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, NULL, 0, "abcd") == 4,
Hi Martin,
On 5/18/20 2:15 PM, Martin Storsjo wrote:
- int bufsizes[] = { 0, 1, sizeof buffer };
Other parts of the file use sizeof with parentheses. Could you please also add it here?
- unsigned int i, j;
- for (j = 0; j < sizeof bufsizes / sizeof bufsizes[0]; j++) {
Please use ARRAY_SIZE(bufsizes).
Thanks, Piotr