diff options
| author | Markus Mittendrein <maxmitti@maxmitti.tk> | 2022-01-08 20:27:28 +0100 |
|---|---|---|
| committer | Markus Mittendrein <maxmitti@maxmitti.tk> | 2022-01-08 20:27:28 +0100 |
| commit | 3d69e19c8f7046b4171597c778bdc82fe8d53bda (patch) | |
| tree | d1bef1a6038fcc51614301f9aab35ff52eb5c3be /include | |
| parent | e007972181e0385eb738970ee4fcc5abcc2127b9 (diff) | |
| download | cxxformat-3d69e19c8f7046b4171597c778bdc82fe8d53bda.tar.gz cxxformat-3d69e19c8f7046b4171597c778bdc82fe8d53bda.zip | |
Restrict parseNumber to unsigned types and throw when out of range
Diffstat (limited to 'include')
| -rw-r--r-- | include/cxxformat/core.hpp | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/include/cxxformat/core.hpp b/include/cxxformat/core.hpp index 55d1629..4e9858b 100644 --- a/include/cxxformat/core.hpp +++ b/include/cxxformat/core.hpp @@ -188,29 +188,24 @@ namespace format { return std::nullopt; } - template<std::integral T = int> - constexpr std::pair<std::optional<T>, std::size_t> parseNumber(std::string_view s, std::size_t pos) noexcept + template<std::unsigned_integral T = unsigned int> + constexpr std::pair<std::optional<T>, std::size_t> parseNumber(std::string_view s, std::size_t pos) { if (pos >= s.size()) { return {std::nullopt, pos}; } - bool isNegative = (std::signed_integral<T> && s[pos] == '-'); - auto startPos = isNegative ? pos + 1 : pos; - if (startPos >= s.size()) - { - return {std::nullopt, pos}; - } - - auto d = digit<T>(s[startPos]); + const auto d = digit<T>(s[pos]); if (!d) { return {std::nullopt, pos}; } + constexpr auto max = std::numeric_limits<T>::max(); + T val{*d}; - auto p = startPos + 1; + auto p = pos + 1; for (; p < s.size(); ++p) { auto nextD = digit<T>(s[p]); @@ -219,10 +214,14 @@ namespace format { break; } + if (val > max / 10 || val * 10 > max - *nextD) + { + throw std::out_of_range{"Number is too big for the target type and would overflow"}; + } val *= 10; val += *nextD; } - return {isNegative ? -val : val, p}; + return {val, p}; } constexpr auto parseSpec(std::string_view fmt, std::size_t pos, ArgIndex nextArg) |
