diff options
author | Sahan Fernando <sahan.h.fernando@gmail.com> | 2020-12-20 16:27:33 +1100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-21 00:15:44 +0100 |
commit | f469f44cc62af6a955da6fb69e26c0ef49341c4a (patch) | |
tree | 55084c2cd5be3b4d56237b3aceb2e6dd48051c90 /AK | |
parent | 37df4bbd9060fdc08d0632d06b167e9bae36a0f8 (diff) | |
download | serenity-f469f44cc62af6a955da6fb69e26c0ef49341c4a.zip |
AK: Check for overflow in StringUtils::convert_to_int
Diffstat (limited to 'AK')
-rw-r--r-- | AK/StringUtils.cpp | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/AK/StringUtils.cpp b/AK/StringUtils.cpp index 5310476d83..9a9da8aa6e 100644 --- a/AK/StringUtils.cpp +++ b/AK/StringUtils.cpp @@ -103,7 +103,7 @@ Optional<T> convert_to_int(const StringView& str) if (str_trimmed.is_empty()) return {}; - bool negative = false; + T sign = 1; size_t i = 0; const auto characters = str_trimmed.characters_without_null_termination(); @@ -111,17 +111,22 @@ Optional<T> convert_to_int(const StringView& str) if (str_trimmed.length() == 1) return {}; i++; - negative = (characters[0] == '-'); + if (characters[0] == '-') + sign = -1; } T value = 0; for (; i < str_trimmed.length(); i++) { if (characters[i] < '0' || characters[i] > '9') return {}; - value = value * 10; - value += characters[i] - '0'; + + if (__builtin_mul_overflow(value, 10, &value)) + return {}; + + if (__builtin_add_overflow(value, sign * (characters[i] - '0'), &value)) + return {}; } - return negative ? -value : value; + return value; } template Optional<i8> convert_to_int(const StringView& str); @@ -143,8 +148,11 @@ Optional<T> convert_to_uint(const StringView& str) if (characters[i] < '0' || characters[i] > '9') return {}; - value = value * 10; - value += characters[i] - '0'; + if (__builtin_mul_overflow(value, 10, &value)) + return {}; + + if (__builtin_add_overflow(value, characters[i] - '0', &value)) + return {}; } return value; } @@ -163,10 +171,13 @@ Optional<T> convert_to_uint_from_hex(const StringView& str) T value = 0; const auto count = str_trimmed.length(); + const T upper_bound = AK::NumericLimits<T>::max(); for (size_t i = 0; i < count; i++) { char digit = str_trimmed[i]; u8 digit_val; + if (value > (upper_bound >> 4)) + return {}; if (digit >= '0' && digit <= '9') { digit_val = digit - '0'; |