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