Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions include/boost/json/basic_parser_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ parse_comment(const char* p,
st_.pop(st);
switch(st)
{
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
case state::com1: goto do_com1;
case state::com2: goto do_com2;
case state::com3: goto do_com3;
Expand Down Expand Up @@ -723,7 +723,7 @@ resume_value(const char* p,
st_.peek(st);
switch(st)
{
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
case state::lit1:
return parse_literal(p, detail::literals_c<detail::literals::resume>() );

Expand Down Expand Up @@ -859,7 +859,7 @@ parse_literal(const char* p, Literal)
}
else
{
BOOST_JSON_UNREACHABLE();
BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
}

cs += sz;
Expand Down Expand Up @@ -947,7 +947,7 @@ parse_literal(const char* p, Literal)
ec_)))
return fail(cs.begin());
break;
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
}

cs += size;
Expand Down Expand Up @@ -977,7 +977,7 @@ parse_string(const char* p,
st_.pop(total);
switch(st)
{
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
case state::str2: goto do_str2;
case state::str8: goto do_str8;
case state::str1: break;
Expand Down Expand Up @@ -1166,7 +1166,7 @@ parse_escaped(
st_.pop(st);
switch(st)
{
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
case state::str3: goto do_str3;
case state::str4: goto do_str4;
case state::str5: goto do_str5;
Expand Down Expand Up @@ -1714,7 +1714,7 @@ parse_object(const char* p,
st_.pop(size);
switch(st)
{
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
case state::obj1: goto do_obj1;
case state::obj2: goto do_obj2;
case state::obj3: goto do_obj3;
Expand Down Expand Up @@ -1883,7 +1883,7 @@ parse_array(const char* p,
st_.pop(size);
switch(st)
{
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
case state::arr1: goto do_arr1;
case state::arr2: goto do_arr2;
case state::arr3: goto do_arr3;
Expand Down Expand Up @@ -2133,7 +2133,7 @@ parse_number(const char* p,
st_.pop(st);
switch(st)
{
default: BOOST_JSON_UNREACHABLE();
default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE
case state::num1: goto do_num1;
case state::num2: goto do_num2;
case state::num3: goto do_num3;
Expand Down
49 changes: 48 additions & 1 deletion test/basic_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,8 @@ class basic_parser_test
TEST_GOOD("1000000000000000000000000.000000000001");
TEST_GOOD("1000000000000000000000000.0e1 ");
TEST_GOOD("1000000000000000000000000.0 ");

TEST_GOOD("1000000000.1000000000 ");
TEST_GOOD("100000000000000000000e+2147483647");

TEST_BAD("");
TEST_BAD("- ");
Expand Down Expand Up @@ -1752,6 +1752,52 @@ class basic_parser_test
#pragma warning(pop)
#endif

struct null_handler
{
constexpr static std::size_t max_object_size = std::size_t(-1);
constexpr static std::size_t max_array_size = std::size_t(-1);
constexpr static std::size_t max_key_size = std::size_t(-1);
constexpr static std::size_t max_string_size = std::size_t(-1);

bool on_document_begin( system::error_code& ) { return true; }
bool on_document_end( system::error_code& ) { return true; }
bool on_object_begin( system::error_code& ) { return true; }
bool on_object_end( std::size_t, system::error_code& ) { return true; }
bool on_array_begin( system::error_code& ) { return true; }
bool on_array_end( std::size_t, system::error_code& ) { return true; }
bool on_key_part( string_view, std::size_t, system::error_code& ) { return true; }
bool on_key( string_view, std::size_t, system::error_code& ) { return true; }
bool on_string_part( string_view, std::size_t, system::error_code& ) { return true; }
bool on_string( string_view, std::size_t, system::error_code& ) { return true; }
bool on_number_part( string_view, system::error_code&) { return true; }
bool on_int64( std::int64_t, string_view, system::error_code& ) { return true; }
bool on_uint64( std::uint64_t, string_view, system::error_code& ) { return true; }
bool on_double( double, string_view, system::error_code& ) { return true; }
bool on_bool( bool, system::error_code& ) { return true; }
bool on_null( system::error_code& ) { return true; }
bool on_comment_part( string_view, system::error_code& ) { return true; }
bool on_comment( string_view, system::error_code& ) { return true; }
};

void
testManualFail()
{
basic_parser<null_handler> p({});
p.fail( system::error_code() );
BOOST_TEST( !p.done() );
BOOST_TEST( p.last_error() == error::incomplete );
BOOST_TEST( p.last_error().has_location() );

p.reset();

system::error_code ec;
p.write_some(false, "null", 4, ec);
BOOST_TEST( p.done() );
p.fail( make_error_code(error::array_too_large) );
BOOST_TEST( !p.done() );
BOOST_TEST( p.last_error() == error::array_too_large );
}

void
run()
{
Expand All @@ -1776,6 +1822,7 @@ class basic_parser_test
testNumberLiteral();
testStickyErrors();
testStdTypes();
testManualFail();
}
};

Expand Down
158 changes: 139 additions & 19 deletions test/limits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,52 @@ class limits_test
BOOST_TEST(ec.has_location());
}

// string in parser, fails at the beginning of the 2nd escape sequence
{
stream_parser p;
system::error_code ec;
p.write_some("\"", 1, ec);
BOOST_TEST( !ec.failed() );
for(std::size_t i = 0; i < string::max_size(); ++i)
{
p.write_some("0", 1, ec);
}
p.write_some("\\n\\", 3, ec);
BOOST_TEST(ec == error::string_too_large);
BOOST_TEST(ec.has_location());
}

// string in parser, fails at the beginning of the 2nd
// (unicode) escape sequence
{
stream_parser p;
system::error_code ec;
p.write_some("\"", 1, ec);
BOOST_TEST( !ec.failed() );
for(std::size_t i = 0; i < string::max_size(); ++i)
{
p.write_some("0", 1, ec);
}
p.write_some("\\n\\u", 4, ec);
BOOST_TEST(ec == error::string_too_large);
BOOST_TEST(ec.has_location());
}

// string in parser, fails after the last escape
{
stream_parser p;
system::error_code ec;
p.write_some("\"", 1, ec);
BOOST_TEST( !ec.failed() );
for(std::size_t i = 0; i < string::max_size(); ++i)
{
p.write_some("0", 1, ec);
}
p.write_some("\\n0", 3, ec);
BOOST_TEST(ec == error::string_too_large);
BOOST_TEST(ec.has_location());
}

// key in parser
{
stream_parser p;
Expand Down Expand Up @@ -353,30 +399,104 @@ class limits_test
testNumber()
{
// very long floating point number
std::array<char, string::max_size() + 1> buffer;
buffer.fill('0');
buffer.data()[1] = '.';
{
std::array<char, string::max_size() + 1> buffer;
buffer.fill('0');
buffer.data()[1] = '.';

parse_options precise;
precise.numbers = number_precision::precise;
parse_options precise;
precise.numbers = number_precision::precise;

stream_parser p( {}, precise );
system::error_code ec;
p.write( buffer.data(), 1, ec );
BOOST_TEST_THROWS_WITH_LOCATION(
p.write( buffer.data() + 1, buffer.size() - 1, ec ));
BOOST_TEST( !ec );
stream_parser p( {}, precise );
system::error_code ec;
p.write( buffer.data(), 1, ec );
BOOST_TEST_THROWS_WITH_LOCATION(
p.write( buffer.data() + 1, buffer.size() - 1, ec ));
BOOST_TEST( !ec );

// now we make the number one character shorter
p.reset();
p.write( buffer.data(), 1, ec );
BOOST_TEST( !ec );

p.write( buffer.data() + 1, buffer.size() - 2, ec );
BOOST_TEST( !ec );

auto jv = p.release();
BOOST_TEST( jv.as_double() == 0 );
}

#ifndef BOOST_JSON_NO_LONG_TESTS
// number with too many digits before decimal point
{
stream_parser p;
system::error_code ec;
std::string number(static_cast<std::size_t>(INT_MAX) + 19, '1');
p.write_some(number, ec);
BOOST_TEST( !ec.failed() );

// now we make the number one character shorter
p.reset();
p.write( buffer.data(), 1, ec );
BOOST_TEST( !ec );
p.write_some("1", 1, ec);
BOOST_TEST(ec == error::exponent_overflow);
BOOST_TEST(ec.has_location());
}

// number with too many digits after decimal point
{
stream_parser p;
system::error_code ec;
p.write_some("0.", 2, ec);
BOOST_TEST( !ec.failed() );
std::string number(static_cast<std::size_t>(INT_MAX), '0');
p.write_some(number, ec);
BOOST_TEST( !ec.failed() );

p.write_some("0", 1, ec);
BOOST_TEST(ec == error::exponent_overflow);
BOOST_TEST(ec.has_location());
}

p.write( buffer.data() + 1, buffer.size() - 2, ec );
BOOST_TEST( !ec );
// number with non-zero mantissa, many digits after decimal point,
// and overflowing negative exponent
{
stream_parser p;
system::error_code ec;
p.write_some("0.", 2, ec);
BOOST_TEST( !ec.failed() );
std::string number(static_cast<std::size_t>(INT_MAX) - 308, '0');
p.write_some(number, ec);
BOOST_TEST( !ec.failed() );
p.write_some("1e-", 3, ec);
BOOST_TEST( !ec.failed() );
p.write_some("2147483647", 10, ec);
BOOST_TEST( !ec.failed() );
// 0.(INT_MAX - 308 zeroes)1e-2147483647

p.write_some(" ", 1, ec);
BOOST_TEST(ec == error::exponent_overflow);
BOOST_TEST(ec.has_location());
}

auto jv = p.release();
BOOST_TEST( jv.as_double() == 0 );
// number with non-zero mantissa, many digits before decimal point,
// and overflowing positive exponent
{
stream_parser p;
system::error_code ec;
p.write_some("1", 1, ec);
BOOST_TEST( !ec.failed() );
std::string number(static_cast<std::size_t>(INT_MAX) - 289, '0');
p.write_some(number, ec);
BOOST_TEST( !ec.failed() );
p.write_some("1e+", 3, ec);
BOOST_TEST( !ec.failed() );
p.write_some("2147483647", 10, ec);
BOOST_TEST( !ec.failed() );
// 1(INT_MAX - 289 zeroes)1e+2147483647

p.write_some(" ", 1, ec);
BOOST_TEST(ec == error::exponent_overflow);
BOOST_TEST(ec.has_location());
}
#endif // BOOST_JSON_NO_LONG_TESTS
}

void
Expand Down
11 changes: 11 additions & 0 deletions test/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,17 @@ class object_test
{
object o;
}
{
key_value_pair kp("a", "b");
}
{
// this test is mostly for getting more test coverage
monotonic_resource mr;
std::pair<string_view, json::value> p("k", "v");
key_value_pair kp(p, &mr);
BOOST_TEST(kp.key() == "k");
BOOST_TEST(kp.value() == "v");
}
}

void
Expand Down
Loading