Skip to content

Commit 3d751ad

Browse files
committed
handle bias overflow
1 parent dd5494b commit 3d751ad

File tree

3 files changed

+123
-3
lines changed

3 files changed

+123
-3
lines changed

.drone.star

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def main(ctx):
1919
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),
2020
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),
2121
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),
22-
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),
22+
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),
2323
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),
2424
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),
2525
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),

include/boost/json/basic_parser_impl.hpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,8 +2336,13 @@ parse_number(const char* p,
23362336
if(BOOST_JSON_UNLIKELY(
23372337
c >= '0' && c <= '9'))
23382338
{
2339+
if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2340+
{
2341+
BOOST_STATIC_CONSTEXPR source_location loc
2342+
= BOOST_CURRENT_LOCATION;
2343+
return fail(cs.begin(), error::exponent_overflow, &loc);
2344+
}
23392345
++cs;
2340-
// VFALCO check overflow
23412346
++num.bias;
23422347
}
23432348
else if(BOOST_JSON_LIKELY(
@@ -2541,6 +2546,12 @@ parse_number(const char* p,
25412546
if(!no_parsing && BOOST_JSON_LIKELY(
25422547
num.mant <= 9007199254740991)) // 2^53-1
25432548
{
2549+
if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2550+
{
2551+
BOOST_STATIC_CONSTEXPR source_location loc
2552+
= BOOST_CURRENT_LOCATION;
2553+
return fail(cs.begin(), error::exponent_overflow, &loc);
2554+
}
25442555
--num.bias;
25452556
num.mant = 10 * num.mant + ( c - '0' );
25462557
}
@@ -2668,14 +2679,42 @@ parse_number(const char* p,
26682679
BOOST_ASSERT(num.exp >= 0);
26692680
if ( num.frac )
26702681
{
2671-
if (BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2682+
if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
26722683
{
2684+
// if exponent overflowed, bias is a very large negative
2685+
// number, and mantissa isn't zero, then we cannot parse the
2686+
// number correctly
2687+
if(BOOST_JSON_UNLIKELY(
2688+
(num.exp == INT_MAX) &&
2689+
(num.bias < 0) &&
2690+
(num.exp + num.bias < 308) &&
2691+
num.mant ))
2692+
{
2693+
BOOST_STATIC_CONSTEXPR source_location loc
2694+
= BOOST_CURRENT_LOCATION;
2695+
return fail(cs.begin(), error::exponent_overflow, &loc);
2696+
}
2697+
26732698
num.bias = 0;
26742699
num.exp = INT_MAX;
26752700
}
26762701
}
26772702
else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
26782703
{
2704+
// if exponent overflowed, bias is a very large positive number,
2705+
// and mantissa isn't zero, then we cannot parse the
2706+
// number correctly
2707+
if(BOOST_JSON_UNLIKELY(
2708+
(num.exp == INT_MAX) &&
2709+
(num.bias > 0) &&
2710+
(num.exp - num.bias < 308) &&
2711+
num.mant ))
2712+
{
2713+
BOOST_STATIC_CONSTEXPR source_location loc
2714+
= BOOST_CURRENT_LOCATION;
2715+
return fail(cs.begin(), error::exponent_overflow, &loc);
2716+
}
2717+
26792718
num.bias = 0;
26802719
num.exp = INT_MAX;
26812720
}

test/stream_parser.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,86 @@ R"xx({
12951295

12961296
//------------------------------------------------------
12971297

1298+
void
1299+
testLongNumberOverlfow()
1300+
{
1301+
#ifdef BOOST_JSON_EXPENSIVE_TESTS
1302+
std::array<char, 1000> zeroes;
1303+
zeroes.fill('0');
1304+
1305+
stream_parser p;
1306+
{
1307+
p.write("1", 1);
1308+
1309+
std::size_t count = 0;
1310+
while( static_cast<std::size_t>( INT_MAX - zeroes.size() ) > count )
1311+
count += p.write( zeroes.data(), zeroes.size() );
1312+
1313+
error_code ec;
1314+
p.write(zeroes.data(), zeroes.size(), ec);
1315+
BOOST_TEST( ec == error::exponent_overflow );
1316+
}
1317+
1318+
p.reset();
1319+
{
1320+
p.write("0.", 2);
1321+
1322+
std::size_t count = 0;
1323+
while( static_cast<std::size_t>( INT_MAX - zeroes.size() ) > count )
1324+
count += p.write( zeroes.data(), zeroes.size() );
1325+
1326+
error_code ec;
1327+
p.write(zeroes.data(), zeroes.size(), ec);
1328+
BOOST_TEST( ec == error::exponent_overflow );
1329+
}
1330+
1331+
p.reset();
1332+
{
1333+
p.write("0.", 2);
1334+
1335+
int count = INT_MIN;
1336+
while( static_cast<int>( count + zeroes.size() ) < 0 )
1337+
count += static_cast<int>(
1338+
p.write( zeroes.data(), zeroes.size() ));
1339+
1340+
p.write(zeroes.data(), -2 - count);
1341+
p.write("1e", 2);
1342+
// at this point we've filled bias to the brim
1343+
1344+
std::string const int_min = std::to_string(INT_MIN);
1345+
p.write( int_min.data(), int_min.size() );
1346+
1347+
error_code ec;
1348+
p.finish(ec);
1349+
BOOST_TEST( ec == error::exponent_overflow );
1350+
}
1351+
1352+
p.reset();
1353+
{
1354+
std::string const uint64_max
1355+
= std::to_string(18446744073709551615U);
1356+
p.write( uint64_max.data(), uint64_max.size() );
1357+
1358+
std::size_t count = INT_MAX;
1359+
while( static_cast<int>( count - zeroes.size() ) > 0 )
1360+
count -= p.write( zeroes.data(), zeroes.size() );
1361+
1362+
p.write(zeroes.data(), count - 1);
1363+
// at this point we've filled bias to the brim
1364+
1365+
p.write("e", 1);
1366+
std::string const int_max = std::to_string(INT_MAX);
1367+
p.write( int_max.data(), int_max.size() );
1368+
1369+
error_code ec;
1370+
p.finish(ec);
1371+
BOOST_TEST( ec == error::exponent_overflow );
1372+
}
1373+
#endif
1374+
}
1375+
1376+
//------------------------------------------------------
1377+
12981378
void
12991379
run()
13001380
{
@@ -1319,6 +1399,7 @@ R"xx({
13191399
testIssue876();
13201400
testSentinelOverlap();
13211401
testSpecialNumbers();
1402+
testLongNumberOverlfow();
13221403
}
13231404
};
13241405

0 commit comments

Comments
 (0)