Fix parsing of out-of-bounds hex values

fix #1267
This commit is contained in:
compmaniak
2018-10-15 00:30:19 +03:00
committed by Vinnie Falco
parent 1e03de3faf
commit 955b7b31a5
4 changed files with 57 additions and 13 deletions

View File

@@ -1,6 +1,7 @@
Version 186:
* basic_fields uses intrusive base hooks
* Fix parsing of out-of-bounds hex values
--------------------------------------------------------------------------------

View File

@@ -29,6 +29,8 @@
* ([issue 1270]) `basic_fields` uses intrusive base hooks
* ([issue 1267]) Fix parsing of out-of-bounds hex values
* Workaround for http-server-fast and libstdc++

View File

@@ -35,6 +35,12 @@ struct basic_parser_base
//
static std::size_t constexpr max_obs_fold = 4096;
template<class T>
struct is_unsigned_integer:
std::integral_constant<bool,
std::numeric_limits<T>::is_integer &&
! std::numeric_limits<T>::is_signed> {};
enum class state
{
nothing_yet = 0,
@@ -301,9 +307,7 @@ struct basic_parser_base
template<class Iter, class T>
static
typename std::enable_if<
std::numeric_limits<T>::is_integer &&
! std::numeric_limits<T>::is_signed, bool>::type
typename std::enable_if<is_unsigned_integer<T>::value, bool>::type
parse_dec(Iter it, Iter last, T& v)
{
if(it == last)
@@ -325,24 +329,26 @@ struct basic_parser_base
return true;
}
template<class Iter, class Unsigned>
template<class Iter, class T>
static
bool
parse_hex(Iter& it, Unsigned& v)
typename std::enable_if<is_unsigned_integer<T>::value, bool>::type
parse_hex(Iter& it, T& v)
{
unsigned char d;
if(! unhex(d, *it))
return false;
v = d;
for(;;)
T tmp = 0;
do
{
if(! unhex(d, *++it))
break;
auto const v0 = v;
v = 16 * v + d;
if(v < v0)
if(tmp > (std::numeric_limits<T>::max)() / 16)
return false;
tmp *= 16;
if((std::numeric_limits<T>::max)() - tmp < d)
return false;
tmp += d;
}
while(unhex(d, *++it));
v = tmp;
return true;
}

View File

@@ -1249,6 +1249,40 @@ public:
bad ("4294967296");
}
void
testIssue1267()
{
using base = detail::basic_parser_base;
auto const good =
[&](string_view s, std::uint64_t v0)
{
std::uint64_t v;
auto it = s.begin();
auto const result =
base::parse_hex(it, v);
if(BEAST_EXPECTS(result, s))
BEAST_EXPECTS(v == v0, s);
};
auto const bad =
[&](string_view s)
{
std::uint64_t v;
auto it = s.begin();
auto const result =
base::parse_hex(it, v);
BEAST_EXPECTS(! result, s);
};
good("f\r\n", 15);
good("ff\r\n", 255);
good("ffff\r\n", 65535);
good("ffffffffr\n", 4294967295);
good("ffffffffffffffff\r\n", 18446744073709551615ULL);
bad ("\r\n");
bad ("g\r\n");
bad ("10000000000000000\r\n");
bad ("ffffffffffffffffffffff\r\n");
}
//--------------------------------------------------------------------------
void
@@ -1274,6 +1308,7 @@ public:
testFuzz();
testRegression1();
testIssue1211();
testIssue1267();
}
};