summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorMarkus Mittendrein <maxmitti@maxmitti.tk>2022-01-08 20:27:28 +0100
committerMarkus Mittendrein <maxmitti@maxmitti.tk>2022-01-08 20:27:28 +0100
commit3d69e19c8f7046b4171597c778bdc82fe8d53bda (patch)
treed1bef1a6038fcc51614301f9aab35ff52eb5c3be /include
parente007972181e0385eb738970ee4fcc5abcc2127b9 (diff)
downloadcxxformat-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.hpp23
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)