From 3d69e19c8f7046b4171597c778bdc82fe8d53bda Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Sat, 8 Jan 2022 20:27:28 +0100 Subject: Restrict parseNumber to unsigned types and throw when out of range --- include/cxxformat/core.hpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'include') 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 - constexpr std::pair, std::size_t> parseNumber(std::string_view s, std::size_t pos) noexcept + template + constexpr std::pair, 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 && s[pos] == '-'); - auto startPos = isNegative ? pos + 1 : pos; - if (startPos >= s.size()) - { - return {std::nullopt, pos}; - } - - auto d = digit(s[startPos]); + const auto d = digit(s[pos]); if (!d) { return {std::nullopt, pos}; } + constexpr auto max = std::numeric_limits::max(); + T val{*d}; - auto p = startPos + 1; + auto p = pos + 1; for (; p < s.size(); ++p) { auto nextD = digit(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) -- cgit v1.2.3-54-g00ecf