Commit 19c04b99ca for qemu.org
commit 19c04b99cad2aca987cda28671b1e959fc2cb6f7
Author: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri Jun 26 12:17:23 2026 +0200
json-streamer: make brace/bracket count unsigned
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 <pbonzini@redhat.com>
Message-ID: <20260626101727.1727389-4-pbonzini@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Comment tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
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;
}