From 2acdb29a328fcc65babe1fd9ee2767195d8309ab Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Thu, 24 Aug 2023 21:24:08 +0300 Subject: [PATCH] fix reading beyond input buffer This fixes a rare case when the parser first suspends inside a comment, then is given input exactly up to the newline character. Before the fix it proceeded to read past the end of the buffer or hit an assert. --- include/boost/json/basic_parser.hpp | 2 +- include/boost/json/basic_parser_impl.hpp | 8 ++++++++ test/basic_parser.cpp | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/boost/json/basic_parser.hpp b/include/boost/json/basic_parser.hpp index ec4415f1e..9c8576fd0 100644 --- a/include/boost/json/basic_parser.hpp +++ b/include/boost/json/basic_parser.hpp @@ -280,7 +280,7 @@ class basic_parser num1, num2, num3, num4, num5, num6, num7, num8, exp1, exp2, exp3, - val1, val2 + val1, val2, val3 }; struct number diff --git a/include/boost/json/basic_parser_impl.hpp b/include/boost/json/basic_parser_impl.hpp index f4cb1e1ca..09968e444 100644 --- a/include/boost/json/basic_parser_impl.hpp +++ b/include/boost/json/basic_parser_impl.hpp @@ -785,9 +785,17 @@ resume_value(const char* p, p = parse_comment(p, std::false_type(), std::false_type()); if(BOOST_JSON_UNLIKELY(p == sentinel())) return maybe_suspend(p, state::val2); + if(BOOST_JSON_UNLIKELY( p == end_ )) + return maybe_suspend(p, state::val3); BOOST_ASSERT(st_.empty()); return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8); } + + case state::val3: + { + st_.pop(st); + return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8); + } } } diff --git a/test/basic_parser.cpp b/test/basic_parser.cpp index 65012ec55..c698f8a28 100644 --- a/test/basic_parser.cpp +++ b/test/basic_parser.cpp @@ -1109,6 +1109,20 @@ class basic_parser_test // no newline at EOF TEST_GOOD_EXT("1//", enabled); + + { + parse_options po; + po.allow_comments = true; + fail_parser p(po); + error_code ec; + p.write(true, "//", 2, ec); // suspend while inside comment + BOOST_TEST( !ec.failed() ); + p.write(true, " \n1", 2, ec); // input ends comment, + // number starts after current input + BOOST_TEST( !ec.failed() ); + p.write(false, "1", 1, ec); + BOOST_TEST( !ec.failed() ); + } } void