@samitouri / QOSamiQemu / commits / 19c04b99ca

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>

Paolo Bonzini committed Jun 26, 2026 at 12:17 UTC 19c04b99cad2aca987cda28671b1e959fc2cb6f7
2 files changed +23 -5
include/qobject/json-parser.h
+2 -2
@@ -31,8 +31,8 @@ typedef struct JSONMessageParser {
31 void *opaque;
32 JSONLexer lexer;
33 JSONParserContext parser;
34 - int brace_count;
35 - int bracket_count;
34 + unsigned int brace_count;
35 + unsigned int bracket_count;
36 GQueue tokens;
37 uint64_t token_size;
38 } JSONMessageParser;
qobject/json-streamer.c
+21 -3
@@ -41,21 +41,41 @@ void json_message_process_token(JSONLexer *lexer, GString *input,
41 parser->brace_count++;
42 break;
43 case JSON_RCURLY:
44 + if (!parser->brace_count) {
45 + goto end_error_recovery;
46 + }
47 parser->brace_count--;
48 break;
49 case JSON_LSQUARE:
50 parser->bracket_count++;
51 break;
52 case JSON_RSQUARE:
53 + if (!parser->bracket_count) {
54 + goto end_error_recovery;
55 + }
56 parser->bracket_count--;
57 break;
58 case JSON_ERROR:
59 error_setg(&err, "JSON parse error, stray '%s'", input->str);
60 goto out_emit;
61 case JSON_END_OF_INPUT:
62 + /*
63 + * Force the parentheses to appear balanced and the queue
64 + * to be emptied, causing a parse error if it wasn't.
65 + */
66 if (g_queue_is_empty(&parser->tokens)) {
67 return;
68 }
69 + end_error_recovery:
70 + /*
71 + * We come here due to receiving either JSON_ERROR or a
72 + * JSON_R{CURLY,SQUARE}) that is known to be unbalanced.
73 + * If in error recovery, end it immediately. If not in
74 + * error recovery, json_parser_feed() will raise an error
75 + * but error recovery won't be entered at all.
76 + */
77 + parser->brace_count = 0;
78 + parser->bracket_count = 0;
79 break;
80 default:
81 break;
@@ -83,9 +103,7 @@ void json_message_process_token(JSONLexer *lexer, GString *input,
103
104 g_queue_push_tail(&parser->tokens, token);
105
86 - if ((parser->brace_count > 0 || parser->bracket_count > 0)
87 - && parser->brace_count >= 0 && parser->bracket_count >= 0
88 - && type != JSON_END_OF_INPUT) {
106 + if (parser->brace_count > 0 || parser->bracket_count > 0) {
107 return;
108 }
109