From 0eec0eb7e094eb3a50d20b230f732625a704483e Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 10 Mar 2020 12:22:14 +0100 Subject: [PATCH] kernelbase: Don't allow the full Unicode character range in StrToInt* functions. Signed-off-by: Alexandre Julliard --- dlls/kernelbase/string.c | 30 ++++++------- dlls/shlwapi/tests/string.c | 84 +++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 38 deletions(-) diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index bd6ff036430..29cc158202f 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -849,8 +849,7 @@ BOOL WINAPI StrToInt64ExA(const char *str, DWORD flags, LONGLONG *ret) WARN("Unknown flags %#x\n", flags); /* Skip leading space, '+', '-' */ - while (*str == ' ' || (*str >= '\t' && *str <= '\r')) - str = CharNextA(str); + while (*str == ' ' || *str == '\t' || *str == '\n') str++; if (*str == '-') { @@ -913,8 +912,7 @@ BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) WARN("Unknown flags %#x.\n", flags); /* Skip leading space, '+', '-' */ - while (iswspace(*str)) - str++; + while (*str == ' ' || *str == '\t' || *str == '\n') str++; if (*str == '-') { @@ -929,10 +927,10 @@ BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) /* Read hex number */ str += 2; - if (!iswxdigit(*str)) + if (!isxdigit(*str)) return FALSE; - while (iswxdigit(*str)) + while (isxdigit(*str)) { value *= 16; if (*str >= '0' && *str <= '9') @@ -949,10 +947,10 @@ BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) } /* Read decimal number */ - if (!iswdigit(*str)) + if (*str < '0' || *str > '9') return FALSE; - while (iswdigit(*str)) + while (*str >= '0' && *str <= '9') { value *= 10; value += (*str - '0'); @@ -996,7 +994,7 @@ int WINAPI StrToIntA(const char *str) if (!str) return 0; - if (*str == '-' || isdigit(*str)) + if (*str == '-' || (*str >= '0' && *str <= '9')) StrToIntExA(str, 0, &value); return value; @@ -1011,7 +1009,7 @@ int WINAPI StrToIntW(const WCHAR *str) if (!str) return 0; - if (*str == '-' || iswdigit(*str)) + if (*str == '-' || (*str >= '0' && *str <= '9')) StrToIntExW(str, 0, &value); return value; } @@ -1312,11 +1310,11 @@ int WINAPI StrCmpLogicalW(const WCHAR *str, const WCHAR *comp) { if (!*comp) return 1; - else if (iswdigit(*str)) + else if (*str >= '0' && *str <= '9') { int str_value, comp_value; - if (!iswdigit(*comp)) + if (*comp < '0' || *comp > '9') return -1; /* Compare the numbers */ @@ -1329,12 +1327,10 @@ int WINAPI StrCmpLogicalW(const WCHAR *str, const WCHAR *comp) return 1; /* Skip */ - while (iswdigit(*str)) - str++; - while (iswdigit(*comp)) - comp++; + while (*str >= '0' && *str <= '9') str++; + while (*comp >= '0' && *comp <= '9') comp++; } - else if (iswdigit(*comp)) + else if (*comp >= '0' && *comp <= '9') return 1; else { diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c index 927c8012cc5..77c108e38bf 100644 --- a/dlls/shlwapi/tests/string.c +++ b/dlls/shlwapi/tests/string.c @@ -76,6 +76,7 @@ typedef struct tagStrToIntResult int str_to_int; LONGLONG str_to_int64_ex; LONGLONG str_to_int64_hex; + BOOL failure; } StrToIntResult; static const StrToIntResult StrToInt_results[] = { @@ -89,11 +90,12 @@ static const StrToIntResult StrToInt_results[] = { { "0x2bdc546291f4b1", 0, 0, ((LONGLONG)0x2bdc54 << 32) | 0x6291f4b1 }, { "+0x44f4", 0, 0, 0x44f4 }, { "-0x44fd", 0, 0, 0x44fd }, - { "+ 88987", 0, 0, 0 }, - { "- 55", 0, 0, 0 }, - { "- 0", 0, 0, 0 }, - { "+ 0x44f4", 0, 0, 0 }, - { "--0x44fd", 0, 0, 0 }, + { "+ 88987", 0, 0, 0, TRUE }, + + { "- 55", 0, 0, 0, TRUE }, + { "- 0", 0, 0, 0, TRUE }, + { "+ 0x44f4", 0, 0, 0, TRUE }, + { "--0x44fd", 0, 0, 0, TRUE }, { " 1999", 0, 1999, 1999 }, { " +88987", 0, 88987, 88987 }, { " 012", 0, 12, 12 }, @@ -101,6 +103,10 @@ static const StrToIntResult StrToInt_results[] = { { " 0x44ff", 0, 0, 0x44ff }, { " +0x44f4", 0, 0, 0x44f4 }, { " -0x44fd", 0, 0, 0x44fd }, + { "\t\n +3", 0, 3, 3 }, + { "\v+4", 0, 0, 0, TRUE }, + { "\f+5", 0, 0, 0, TRUE }, + { "\r+6", 0, 0, 0, TRUE }, { NULL, 0, 0, 0 } }; @@ -488,8 +494,10 @@ static void test_StrToIntExA(void) { return_val = -1; bRet = StrToIntExA(result->string,0,&return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n", result->string, return_val); @@ -501,8 +509,10 @@ static void test_StrToIntExA(void) { return_val = -1; bRet = StrToIntExA(result->string,STIF_SUPPORT_HEX,&return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n", result->string, return_val); @@ -522,8 +532,10 @@ static void test_StrToIntExW(void) return_val = -1; MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); bRet = StrToIntExW(szBuff, 0, &return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == (int)result->str_to_int64_ex, "converted '%s' wrong (%d)\n", result->string, return_val); @@ -536,13 +548,23 @@ static void test_StrToIntExW(void) return_val = -1; MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); bRet = StrToIntExW(szBuff, STIF_SUPPORT_HEX, &return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %d instead of failure for '%s'\n", return_val, result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == (int)result->str_to_int64_hex, "converted '%s' wrong (%d)\n", result->string, return_val); result++; } + + return_val = -1; + bRet = StrToIntExW(L"\x0661\x0662", 0, &return_val); + ok( !bRet, "Returned %d for Unicode digits\n", return_val ); + bRet = StrToIntExW(L"\x07c3\x07c4", 0, &return_val); + ok( !bRet, "Returned %d for Unicode digits\n", return_val ); + bRet = StrToIntExW(L"\xa0-2", 0, &return_val); + ok( !bRet, "Returned %d for Unicode space\n", return_val ); } static void test_StrToInt64ExA(void) @@ -561,8 +583,11 @@ static void test_StrToInt64ExA(void) { return_val = -1; bRet = pStrToInt64ExA(result->string,0,&return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %s instead of failure for '%s'\n", + wine_dbgstr_longlong(return_val), result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%s)\n", result->string, wine_dbgstr_longlong(return_val)); @@ -574,8 +599,11 @@ static void test_StrToInt64ExA(void) { return_val = -1; bRet = pStrToInt64ExA(result->string,STIF_SUPPORT_HEX,&return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %s instead of failure for '%s'\n", + wine_dbgstr_longlong(return_val), result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%s)\n", result->string, wine_dbgstr_longlong(return_val)); @@ -601,8 +629,11 @@ static void test_StrToInt64ExW(void) return_val = -1; MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); bRet = pStrToInt64ExW(szBuff, 0, &return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %s instead of failure for '%s'\n", + wine_dbgstr_longlong(return_val), result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == result->str_to_int64_ex, "converted '%s' wrong (%s)\n", result->string, wine_dbgstr_longlong(return_val)); @@ -615,13 +646,24 @@ static void test_StrToInt64ExW(void) return_val = -1; MultiByteToWideChar(CP_ACP, 0, result->string, -1, szBuff, ARRAY_SIZE(szBuff)); bRet = pStrToInt64ExW(szBuff, STIF_SUPPORT_HEX, &return_val); - ok(!bRet || return_val != -1, "No result returned from '%s'\n", - result->string); + if (result->failure) + ok(!bRet, "Got %s instead of failure for '%s'\n", + wine_dbgstr_longlong(return_val), result->string); + else + ok(bRet, "Failed for '%s'\n", result->string); if (bRet) ok(return_val == result->str_to_int64_hex, "converted '%s' wrong (%s)\n", result->string, wine_dbgstr_longlong(return_val)); result++; } + + return_val = -1; + bRet = pStrToInt64ExW(L"\x0661\x0662", 0, &return_val); + ok( !bRet, "Returned %s for Unicode digits\n", wine_dbgstr_longlong(return_val) ); + bRet = pStrToInt64ExW(L"\x07c3\x07c4", 0, &return_val); + ok( !bRet, "Returned %s for Unicode digits\n", wine_dbgstr_longlong(return_val) ); + bRet = pStrToInt64ExW(L"\xa0-2", 0, &return_val); + ok( !bRet, "Returned %s for Unicode space\n", wine_dbgstr_longlong(return_val) ); } static void test_StrDupA(void)