json: Don't pass null @tokens to json_parser_parse()

json_parser_parse() normally returns the QObject on success.  Except
it returns null when its @tokens argument is null.

Its only caller json_message_process_token() passes null @tokens when
emitting a lexical error.  The call is a rather opaque way to say json
= NULL then.

Simplify matters by lifting the assignment to json out of the emit
path: initialize json to null, set it to the value of
json_parser_parse() when there's no lexical error.  Drop the special
case from json_parser_parse().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180823164025.12553-36-armbru@redhat.com>
This commit is contained in:
Markus Armbruster 2018-08-23 18:40:02 +02:00
parent 62815d85ae
commit ff281a272f
2 changed files with 12 additions and 17 deletions

View File

@ -546,10 +546,6 @@ QObject *json_parser_parse(GQueue *tokens, va_list *ap, Error **errp)
JSONParserContext ctxt = { .buf = tokens }; JSONParserContext ctxt = { .buf = tokens };
QObject *result; QObject *result;
if (!tokens) {
return NULL;
}
result = parse_value(&ctxt, ap); result = parse_value(&ctxt, ap);
error_propagate(errp, ctxt.err); error_propagate(errp, ctxt.err);

View File

@ -39,9 +39,9 @@ void json_message_process_token(JSONLexer *lexer, GString *input,
JSONTokenType type, int x, int y) JSONTokenType type, int x, int y)
{ {
JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer); JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
QObject *json = NULL;
Error *err = NULL; Error *err = NULL;
JSONToken *token; JSONToken *token;
QObject *json;
switch (type) { switch (type) {
case JSON_LCURLY: case JSON_LCURLY:
@ -72,34 +72,33 @@ void json_message_process_token(JSONLexer *lexer, GString *input,
g_queue_push_tail(parser->tokens, token); g_queue_push_tail(parser->tokens, token);
if (type == JSON_ERROR) { if (type == JSON_ERROR) {
goto out_emit_bad; goto out_emit;
} else if (parser->brace_count < 0 || }
if (parser->brace_count < 0 ||
parser->bracket_count < 0 || parser->bracket_count < 0 ||
(parser->brace_count == 0 && (parser->brace_count == 0 &&
parser->bracket_count == 0)) { parser->bracket_count == 0)) {
json = json_parser_parse(parser->tokens, parser->ap, &err);
parser->tokens = NULL;
goto out_emit; goto out_emit;
} else if (parser->token_size > MAX_TOKEN_SIZE || }
if (parser->token_size > MAX_TOKEN_SIZE ||
g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT || g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT ||
parser->bracket_count + parser->brace_count > MAX_NESTING) { parser->bracket_count + parser->brace_count > MAX_NESTING) {
/* Security consideration, we limit total memory allocated per object /* Security consideration, we limit total memory allocated per object
* and the maximum recursion depth that a message can force. * and the maximum recursion depth that a message can force.
*/ */
goto out_emit_bad; goto out_emit;
} }
return; return;
out_emit_bad:
/*
* Clear out token list and tell the parser to emit an error
* indication by passing it a NULL list
*/
json_message_free_tokens(parser);
out_emit: out_emit:
/* send current list of tokens to parser and reset tokenizer */
parser->brace_count = 0; parser->brace_count = 0;
parser->bracket_count = 0; parser->bracket_count = 0;
json = json_parser_parse(parser->tokens, parser->ap, &err); json_message_free_tokens(parser);
parser->tokens = g_queue_new(); parser->tokens = g_queue_new();
parser->token_size = 0; parser->token_size = 0;
parser->emit(parser->opaque, json, err); parser->emit(parser->opaque, json, err);