From: Paolo Bonzini <[email protected]> It makes no sense to let brace_count and bracket_count go negative, also because it immediately ends error recovery and sets them both back to zero. Instead set them to zero *before* choosing whether to process the token queue; this makes it possible to have the fields as unsigned.
Note that JSON_END_OF_INPUT now forces the parentheses to appear balanced, so that the queue is emptied and an error is reported; hence, the "type != JSON_END_OF_INPUT" condition can be removed. Signed-off-by: Paolo Bonzini <[email protected]> Message-ID: <[email protected]> Reviewed-by: Markus Armbruster <[email protected]> [Comment tweaked] Signed-off-by: Markus Armbruster <[email protected]> --- include/qobject/json-parser.h | 4 ++-- qobject/json-streamer.c | 24 +++++++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/qobject/json-parser.h b/include/qobject/json-parser.h index 4c3d89f751..0cf6932ecd 100644 --- a/include/qobject/json-parser.h +++ b/include/qobject/json-parser.h @@ -31,8 +31,8 @@ typedef struct JSONMessageParser { void *opaque; JSONLexer lexer; JSONParserContext parser; - int brace_count; - int bracket_count; + unsigned int brace_count; + unsigned int bracket_count; GQueue tokens; uint64_t token_size; } JSONMessageParser; diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c index 6c4f99b3e7..e18fd9bb0e 100644 --- a/qobject/json-streamer.c +++ b/qobject/json-streamer.c @@ -41,21 +41,41 @@ void json_message_process_token(JSONLexer *lexer, GString *input, parser->brace_count++; break; case JSON_RCURLY: + if (!parser->brace_count) { + goto end_error_recovery; + } parser->brace_count--; break; case JSON_LSQUARE: parser->bracket_count++; break; case JSON_RSQUARE: + if (!parser->bracket_count) { + goto end_error_recovery; + } parser->bracket_count--; break; case JSON_ERROR: error_setg(&err, "JSON parse error, stray '%s'", input->str); goto out_emit; case JSON_END_OF_INPUT: + /* + * Force the parentheses to appear balanced and the queue + * to be emptied, causing a parse error if it wasn't. + */ if (g_queue_is_empty(&parser->tokens)) { return; } + end_error_recovery: + /* + * We come here due to receiving either JSON_ERROR or a + * JSON_R{CURLY,SQUARE}) that is known to be unbalanced. + * If in error recovery, end it immediately. If not in + * error recovery, json_parser_feed() will raise an error + * but error recovery won't be entered at all. + */ + parser->brace_count = 0; + parser->bracket_count = 0; break; default: break; @@ -83,9 +103,7 @@ void json_message_process_token(JSONLexer *lexer, GString *input, g_queue_push_tail(&parser->tokens, token); - if ((parser->brace_count > 0 || parser->bracket_count > 0) - && parser->brace_count >= 0 && parser->bracket_count >= 0 - && type != JSON_END_OF_INPUT) { + if (parser->brace_count > 0 || parser->bracket_count > 0) { return; } -- 2.54.0
