From 748be364e5ee85cf92dfd0300468afc6bc36cbd2 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Fri, 2 Dec 2011 01:16:56 +0100 Subject: Fixed range check on TryParse() for u32. On x86-64, "unsigned long" is 64 bits wide, so it is possible for a number to not trigger a range error on strtoul() but still not fit inside an u32. An extra check is added to ensure that 32-bit and 64-bit builds will accept the same numbers. --- Source/Core/Common/Src/StringUtil.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'Source/Core/Common/Src/StringUtil.cpp') diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 18a3575086..94f01e66f8 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -125,7 +125,7 @@ std::string StripQuotes(const std::string& s) bool TryParse(const std::string &str, u32 *const output) { char *endptr = NULL; - u32 value = strtoul(str.c_str(), &endptr, 0); + unsigned long value = strtoul(str.c_str(), &endptr, 0); if (!endptr || *endptr) return false; @@ -133,7 +133,13 @@ bool TryParse(const std::string &str, u32 *const output) if (value == ULONG_MAX && errno == ERANGE) return false; - *output = value; + if (ULONG_MAX > UINT_MAX) { + // Leading bits must be either all 0 or all 1. + if ((~value | UINT_MAX) != ULONG_MAX && (value | UINT_MAX) != ULONG_MAX) + return false; + } + + *output = static_cast(value); return true; } -- cgit v1.2.3 From 27bda2c054f38cdd8b6a04fe939ea006535ae532 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Tue, 13 Dec 2011 02:02:31 +0100 Subject: Fixed range check on TryParse() for u32, again. The code from 748be364e5ee incorrectly accepted -0x100000000 on x86_64. Also if ERANGE is returned by strtoul(), reject the parsed value regardless of what that value is. This fixes invalid values being returned when compiling with Visual C++. Thanks to "cotton" for testing this. --- Source/Core/Common/Src/StringUtil.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Source/Core/Common/Src/StringUtil.cpp') diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 94f01e66f8..cdd1016210 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -130,12 +130,13 @@ bool TryParse(const std::string &str, u32 *const output) if (!endptr || *endptr) return false; - if (value == ULONG_MAX && errno == ERANGE) + if (errno == ERANGE) return false; if (ULONG_MAX > UINT_MAX) { - // Leading bits must be either all 0 or all 1. - if ((~value | UINT_MAX) != ULONG_MAX && (value | UINT_MAX) != ULONG_MAX) + // Note: The typecasts avoid GCC warnings when long is 32 bits wide. + if (value >= static_cast(0x100000000ull) + && value <= static_cast(0xFFFFFFFF00000000ull)) return false; } -- cgit v1.2.3 From 1df7af35e994f651cd628a9cc5c11745381a1cb7 Mon Sep 17 00:00:00 2001 From: skidau Date: Thu, 29 Dec 2011 12:05:36 +1100 Subject: Reset errno to zero before testing it after the strtoul call. Fixes issue 5078. --- Source/Core/Common/Src/StringUtil.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Source/Core/Common/Src/StringUtil.cpp') diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index cdd1016210..664987d350 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -125,6 +125,10 @@ std::string StripQuotes(const std::string& s) bool TryParse(const std::string &str, u32 *const output) { char *endptr = NULL; + + // Reset errno to a value other than ERANGE + errno = 0; + unsigned long value = strtoul(str.c_str(), &endptr, 0); if (!endptr || *endptr) -- cgit v1.2.3