mirror of
https://github.com/nlohmann/json.git
synced 2026-10-05 22:20:30 +00:00
Merge remote-tracking branch 'origin/develop' into claude/fix-issue-3989-db7e45
Signed-off-by: Niels Lohmann <mail@nlohmann.me> # Conflicts: # include/nlohmann/detail/input/lexer.hpp # include/nlohmann/detail/input/parser.hpp # single_include/nlohmann/json.hpp # tests/src/fuzzer-parse_json.cpp
This commit is contained in:
@@ -54,7 +54,8 @@ using parser_callback_t =
|
||||
/*!
|
||||
@brief syntax analysis
|
||||
|
||||
This class implements a recursive descent parser.
|
||||
This class implements an iterative parser that keeps the open containers on
|
||||
an explicit stack and reports what it reads as SAX events.
|
||||
*/
|
||||
template<typename BasicJsonType, typename InputAdapterType>
|
||||
class parser
|
||||
@@ -98,28 +99,9 @@ class parser
|
||||
if (callback)
|
||||
{
|
||||
json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
|
||||
sax_parse_internal<false>(&sdp);
|
||||
|
||||
if (strict)
|
||||
{
|
||||
// in strict mode, input must be completely read
|
||||
if (get_token() != token_type::end_of_input)
|
||||
{
|
||||
sdp.parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::end_of_input, "value"), nullptr));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the caller keeps using the input: position it right after
|
||||
// the value by leaving the character that terminated it
|
||||
m_lexer.release_lookahead();
|
||||
}
|
||||
|
||||
// in case of an error, return a discarded value
|
||||
if (sdp.is_errored())
|
||||
if (!parse_dom(sdp, strict))
|
||||
{
|
||||
result = value_t::discarded;
|
||||
return;
|
||||
@@ -135,26 +117,9 @@ class parser
|
||||
else
|
||||
{
|
||||
json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
|
||||
sax_parse_internal<false>(&sdp);
|
||||
|
||||
if (strict)
|
||||
{
|
||||
// in strict mode, input must be completely read
|
||||
if (get_token() != token_type::end_of_input)
|
||||
{
|
||||
sdp.parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// see above
|
||||
m_lexer.release_lookahead();
|
||||
}
|
||||
|
||||
// in case of an error, return a discarded value
|
||||
if (sdp.is_errored())
|
||||
if (!parse_dom(sdp, strict))
|
||||
{
|
||||
result = value_t::discarded;
|
||||
return;
|
||||
@@ -239,6 +204,46 @@ class parser
|
||||
return result && !error_reported;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief run a DOM SAX parser to completion and position the lexer
|
||||
|
||||
Shared by both branches of @ref parse(): builds no SAX parser itself,
|
||||
but drives an already-constructed @a json_sax_dom_parser or
|
||||
@ref json_sax_dom_callback_parser through @ref sax_parse_internal(),
|
||||
then applies the strict-EOF check (reporting parse_error.101 through
|
||||
@a sdp on failure) or, in non-strict mode, releases the lookahead so
|
||||
the caller can keep reading the input right after the parsed value.
|
||||
|
||||
@param[in,out] sdp the DOM SAX parser to run
|
||||
@param[in] strict whether to expect the last token to be EOF
|
||||
@return whether @a sdp did not report an error
|
||||
*/
|
||||
template<typename DomSax>
|
||||
bool parse_dom(DomSax& sdp, const bool strict)
|
||||
{
|
||||
sax_parse_internal<false>(&sdp);
|
||||
|
||||
if (strict)
|
||||
{
|
||||
// in strict mode, input must be completely read
|
||||
if (get_token() != token_type::end_of_input)
|
||||
{
|
||||
sdp.parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::end_of_input, "value"), nullptr));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the caller keeps using the input: position it right after
|
||||
// the value by leaving the character that terminated it
|
||||
m_lexer.release_lookahead();
|
||||
}
|
||||
|
||||
return !sdp.is_errored();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief parse a JSON value and pass it to a SAX parser
|
||||
|
||||
@@ -554,8 +559,9 @@ class parser
|
||||
|
||||
// We are done with this array. Before we can parse a
|
||||
// new value, we need to evaluate the new state first.
|
||||
// By setting skip_to_state_evaluation to false, we
|
||||
// are effectively jumping to the beginning of this if.
|
||||
// By setting skip_to_state_evaluation to true, the next
|
||||
// iteration skips parsing a value and evaluates the
|
||||
// enclosing state directly.
|
||||
JSON_ASSERT(!states.empty());
|
||||
states.pop_back();
|
||||
skip_to_state_evaluation = true;
|
||||
@@ -639,8 +645,9 @@ class parser
|
||||
|
||||
// We are done with this object. Before we can parse a
|
||||
// new value, we need to evaluate the new state first.
|
||||
// By setting skip_to_state_evaluation to false, we
|
||||
// are effectively jumping to the beginning of this if.
|
||||
// By setting skip_to_state_evaluation to true, the next
|
||||
// iteration skips parsing a value and evaluates the
|
||||
// enclosing state directly.
|
||||
JSON_ASSERT(!states.empty());
|
||||
states.pop_back();
|
||||
skip_to_state_evaluation = true;
|
||||
|
||||
Reference in New Issue
Block a user