handle bias overflow

This commit is contained in:
Dmitry Arkhipov 2023-06-26 21:38:18 +03:00
parent dd5494b202
commit 3d751ad9e5
3 changed files with 123 additions and 3 deletions

View File

@ -19,7 +19,7 @@ def main(ctx):
linux_cxx("Clang 12 arm64", "clang++-12", packages="clang-12 libstdc++-9-dev", llvm_os="focal", llvm_ver="12", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2004:multiarch", environment={'B2_TOOLSET': 'clang-12', 'B2_CXXSTD': '17,20', 'DRONE_JOB_UUID': '7719a1c783m'}, arch="arm64", globalenv=globalenv),
linux_cxx("gcc 11 arm64", "g++-11", packages="g++-11", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2004:multiarch", environment={'B2_TOOLSET': 'gcc-11', 'B2_CXXSTD': '17,2a', 'DRONE_JOB_UUID': '0716d9708dm'}, arch="arm64", globalenv=globalenv),
linux_cxx("docs", "g++", packages="docbook docbook-xml docbook-xsl xsltproc libsaxonhe-java default-jre-headless flex libfl-dev bison unzip rsync", buildtype="docs", buildscript="drone", image="cppalliance/droneubuntu1804:1", environment={'COMMENT': 'docs', 'DRONE_JOB_UUID': 'b6589fc6ab'}, globalenv=globalenv),
linux_cxx("codecov", "g++-8", packages="g++-8", buildtype="codecov", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'codecov.io', 'LCOV_BRANCH_COVERAGE': '0', 'B2_CXXSTD': '11', 'B2_TOOLSET': 'gcc-8', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'CODECOV_TOKEN': {'from_secret': 'codecov_token'}, 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv),
linux_cxx("codecov", "g++-8", packages="g++-8", buildtype="codecov", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'codecov.io', 'LCOV_BRANCH_COVERAGE': '0', 'B2_CXXSTD': '11', 'B2_TOOLSET': 'gcc-8', 'B2_DEFINES': 'BOOST_JSON_EXPENSIVE_TESTS BOOST_NO_STRESS_TEST=1', 'CODECOV_TOKEN': {'from_secret': 'codecov_token'}, 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv),
linux_cxx("Valgrind", "clang++-14", packages="clang-14 libc6-dbg libc++-dev libstdc++-9-dev", llvm_os="jammy", llvm_ver="14", buildscript="drone", buildtype="valgrind", image="cppalliance/droneubuntu2204:1", environment={'COMMENT': 'valgrind', 'B2_TOOLSET': 'clang-14', 'B2_CXXSTD': '11,14,17', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'B2_VARIANT': 'debug', 'B2_TESTFLAGS': 'testing.launcher=valgrind', 'VALGRIND_OPTS': '--error-exitcode=1'}, globalenv=globalenv),
linux_cxx("ASan GCC", "g++-12", packages="g++-12", buildscript="drone", buildtype="boost", image="cppalliance/droneubuntu2204:1", environment={'COMMENT': 'asan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-12', 'B2_CXXSTD': '11,14,17', 'B2_ASAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'DRONE_EXTRA_PRIVILEGED': 'True'}, globalenv=globalenv, privileged=True),
linux_cxx("ASan Clang", "clang++-14", packages="clang-14 libstdc++-10-dev", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2204:1", environment={'COMMENT': 'asan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'clang-14', 'B2_CXXSTD': '11,14,17', 'B2_ASAN': '1', 'B2_DEFINES': 'define=BOOST_NO_STRESS_TEST=1'}, globalenv=globalenv),

View File

@ -2336,8 +2336,13 @@ do_num3:
if(BOOST_JSON_UNLIKELY(
c >= '0' && c <= '9'))
{
if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
{
BOOST_STATIC_CONSTEXPR source_location loc
= BOOST_CURRENT_LOCATION;
return fail(cs.begin(), error::exponent_overflow, &loc);
}
++cs;
// VFALCO check overflow
++num.bias;
}
else if(BOOST_JSON_LIKELY(
@ -2541,6 +2546,12 @@ do_num8:
if(!no_parsing && BOOST_JSON_LIKELY(
num.mant <= 9007199254740991)) // 2^53-1
{
if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
{
BOOST_STATIC_CONSTEXPR source_location loc
= BOOST_CURRENT_LOCATION;
return fail(cs.begin(), error::exponent_overflow, &loc);
}
--num.bias;
num.mant = 10 * num.mant + ( c - '0' );
}
@ -2668,14 +2679,42 @@ do_exp3:
BOOST_ASSERT(num.exp >= 0);
if ( num.frac )
{
if (BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
{
// if exponent overflowed, bias is a very large negative
// number, and mantissa isn't zero, then we cannot parse the
// number correctly
if(BOOST_JSON_UNLIKELY(
(num.exp == INT_MAX) &&
(num.bias < 0) &&
(num.exp + num.bias < 308) &&
num.mant ))
{
BOOST_STATIC_CONSTEXPR source_location loc
= BOOST_CURRENT_LOCATION;
return fail(cs.begin(), error::exponent_overflow, &loc);
}
num.bias = 0;
num.exp = INT_MAX;
}
}
else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
{
// if exponent overflowed, bias is a very large positive number,
// and mantissa isn't zero, then we cannot parse the
// number correctly
if(BOOST_JSON_UNLIKELY(
(num.exp == INT_MAX) &&
(num.bias > 0) &&
(num.exp - num.bias < 308) &&
num.mant ))
{
BOOST_STATIC_CONSTEXPR source_location loc
= BOOST_CURRENT_LOCATION;
return fail(cs.begin(), error::exponent_overflow, &loc);
}
num.bias = 0;
num.exp = INT_MAX;
}

View File

@ -1295,6 +1295,86 @@ R"xx({
//------------------------------------------------------
void
testLongNumberOverlfow()
{
#ifdef BOOST_JSON_EXPENSIVE_TESTS
std::array<char, 1000> zeroes;
zeroes.fill('0');
stream_parser p;
{
p.write("1", 1);
std::size_t count = 0;
while( static_cast<std::size_t>( INT_MAX - zeroes.size() ) > count )
count += p.write( zeroes.data(), zeroes.size() );
error_code ec;
p.write(zeroes.data(), zeroes.size(), ec);
BOOST_TEST( ec == error::exponent_overflow );
}
p.reset();
{
p.write("0.", 2);
std::size_t count = 0;
while( static_cast<std::size_t>( INT_MAX - zeroes.size() ) > count )
count += p.write( zeroes.data(), zeroes.size() );
error_code ec;
p.write(zeroes.data(), zeroes.size(), ec);
BOOST_TEST( ec == error::exponent_overflow );
}
p.reset();
{
p.write("0.", 2);
int count = INT_MIN;
while( static_cast<int>( count + zeroes.size() ) < 0 )
count += static_cast<int>(
p.write( zeroes.data(), zeroes.size() ));
p.write(zeroes.data(), -2 - count);
p.write("1e", 2);
// at this point we've filled bias to the brim
std::string const int_min = std::to_string(INT_MIN);
p.write( int_min.data(), int_min.size() );
error_code ec;
p.finish(ec);
BOOST_TEST( ec == error::exponent_overflow );
}
p.reset();
{
std::string const uint64_max
= std::to_string(18446744073709551615U);
p.write( uint64_max.data(), uint64_max.size() );
std::size_t count = INT_MAX;
while( static_cast<int>( count - zeroes.size() ) > 0 )
count -= p.write( zeroes.data(), zeroes.size() );
p.write(zeroes.data(), count - 1);
// at this point we've filled bias to the brim
p.write("e", 1);
std::string const int_max = std::to_string(INT_MAX);
p.write( int_max.data(), int_max.size() );
error_code ec;
p.finish(ec);
BOOST_TEST( ec == error::exponent_overflow );
}
#endif
}
//------------------------------------------------------
void
run()
{
@ -1319,6 +1399,7 @@ R"xx({
testIssue876();
testSentinelOverlap();
testSpecialNumbers();
testLongNumberOverlfow();
}
};