From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: Anthony Liguori <aliguori@us.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Luiz Capitulino <lcapitulino@redhat.com>,
qemu-devel@nongnu.org, Michael D Roth <mdroth@us.ibm.com>,
Markus Armbruster <armbru@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 10/11] json-streamer: limit the maximum recursion depth and maximum token count
Date: Fri, 11 Mar 2011 17:16:03 -0600 [thread overview]
Message-ID: <4D7AAD33.1000804@linux.vnet.ibm.com> (raw)
In-Reply-To: <1299877249-13433-11-git-send-email-aliguori@us.ibm.com>
On 03/11/2011 03:00 PM, Anthony Liguori wrote:
> The JSON parse we use is a recursive decent parser which means that recursion
> is used to backtrack. To avoid stack overflows from malformed input, we need
> to limit recursion depth.
>
> Fortunately, we know the maximum recursion depth in the message parsing phase
> so we can very easily check for unreasonably deep recursion. If we find that
> emit the current token stream and let the parser handle it. The idea here is
> that hopefully the stream will recover or at least error out gracefully.
>
> We also limit the maximum token count. We don't limit the number of tokens, but
> rather the total memory used for tokens at any given point in time.
>
> Signed-off-by: Anthony Liguori<aliguori@us.ibm.com>
>
> diff --git a/json-streamer.c b/json-streamer.c
> index f7e7a68..c7f43b0 100644
> --- a/json-streamer.c
> +++ b/json-streamer.c
> @@ -18,6 +18,9 @@
> #include "json-lexer.h"
> #include "json-streamer.h"
>
> +#define MAX_TOKEN_SIZE (64ULL<< 20)
> +#define MAX_NESTING (1ULL<< 10)
> +
> static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTokenType type, int x, int y)
> {
> JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
> @@ -49,6 +52,8 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
> qdict_put(dict, "x", qint_from_int(x));
> qdict_put(dict, "y", qint_from_int(y));
>
> + parser->token_size += token->length;
> +
> qlist_append(parser->tokens, dict);
>
> if (parser->brace_count == 0&&
> @@ -56,6 +61,19 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
> parser->emit(parser, parser->tokens);
> QDECREF(parser->tokens);
> parser->tokens = qlist_new();
> + parser->token_size = 0;
> + } else if (parser->token_size> MAX_TOKEN_SIZE ||
> + parser->bracket_count> MAX_NESTING ||
> + parser->brace_count> MAX_NESTING) {
> + /* Security consideration, we limit total memory allocated per object
> + * and the maximum recursion depth that a message can force.
> + */
> + parser->brace_count = 0;
> + parser->bracket_count = 0;
> + parser->emit(parser, parser->tokens);
Should we even bother passing this to the parser? That's a lot stuff to
churn on that we know isn't going to result in anything useful. If there
was a proper object earlier in the stream it would've been emitted when
brace/bracket count reached 0.
I think it might be nicer to do parser->emit(parser, NULL), and fix up
json_parser_parse_err() to check for this and simply return NULL back to
qmp_dispatch_err() or whoever is calling.
I think brace_count < 0 || bracket_count < 0 should get similar treatment.
> + QDECREF(parser->tokens);
> + parser->tokens = qlist_new();
> + parser->token_size = 0;
> }
> }
>
> @@ -66,6 +84,7 @@ void json_message_parser_init(JSONMessageParser *parser,
> parser->brace_count = 0;
> parser->bracket_count = 0;
> parser->tokens = qlist_new();
> + parser->token_size = 0;
>
> json_lexer_init(&parser->lexer, json_message_process_token);
> }
> diff --git a/json-streamer.h b/json-streamer.h
> index 09f3bd7..f09bc4d 100644
> --- a/json-streamer.h
> +++ b/json-streamer.h
> @@ -24,6 +24,7 @@ typedef struct JSONMessageParser
> int brace_count;
> int bracket_count;
> QList *tokens;
> + uint64_t token_size;
> } JSONMessageParser;
>
> void json_message_parser_init(JSONMessageParser *parser,
next prev parent reply other threads:[~2011-03-11 23:16 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-11 21:00 [Qemu-devel] [00/11] QAPI Round 0 (JSON improvements) Anthony Liguori
2011-03-11 21:00 ` [Qemu-devel] [PATCH 01/11] Add hard build dependency on glib Anthony Liguori
2011-03-12 8:09 ` [Qemu-devel] " Paolo Bonzini
2011-03-12 14:52 ` Anthony Liguori
2011-03-11 21:00 ` [Qemu-devel] [PATCH 02/11] qerror: expose a function to format an error Anthony Liguori
2011-03-11 21:08 ` [Qemu-devel] " Anthony Liguori
2011-03-14 19:17 ` Luiz Capitulino
2011-03-14 19:27 ` Anthony Liguori
2011-03-14 19:37 ` Luiz Capitulino
2011-03-14 19:45 ` Anthony Liguori
2011-03-14 20:22 ` Luiz Capitulino
2011-03-14 20:41 ` Anthony Liguori
2011-03-14 20:48 ` Luiz Capitulino
2011-03-14 21:03 ` Anthony Liguori
2011-03-11 21:00 ` [Qemu-devel] [PATCH 03/11] add a generic Error object Anthony Liguori
2011-03-12 11:05 ` Blue Swirl
2011-03-12 14:51 ` Anthony Liguori
2011-03-14 19:18 ` [Qemu-devel] " Luiz Capitulino
2011-03-14 19:34 ` Anthony Liguori
2011-03-14 19:57 ` Luiz Capitulino
2011-03-11 21:00 ` [Qemu-devel] [PATCH 04/11] qerror: split out the reporting bits of QError Anthony Liguori
2011-03-14 19:18 ` [Qemu-devel] " Luiz Capitulino
2011-03-14 19:24 ` Anthony Liguori
2011-03-14 19:30 ` Luiz Capitulino
2011-03-14 20:30 ` Anthony Liguori
2011-03-11 21:00 ` [Qemu-devel] [PATCH 05/11] qerror: add new error message for invalid enum values Anthony Liguori
2011-03-14 19:19 ` [Qemu-devel] " Luiz Capitulino
2011-03-11 21:00 ` [Qemu-devel] [PATCH 06/11] qerror: add JSON parsing error message Anthony Liguori
2011-03-11 21:00 ` [Qemu-devel] [PATCH 07/11] json: propagate error from parser Anthony Liguori
2011-03-11 21:00 ` [Qemu-devel] [PATCH 08/11] json-lexer: reset the lexer state on an invalid token Anthony Liguori
2011-03-14 19:22 ` [Qemu-devel] " Luiz Capitulino
2011-03-14 19:43 ` Anthony Liguori
2011-03-14 20:12 ` Luiz Capitulino
2011-03-14 20:30 ` Anthony Liguori
2011-03-14 20:43 ` Luiz Capitulino
2011-03-11 21:00 ` [Qemu-devel] [PATCH 09/11] json-lexer: limit the maximum size of a given token Anthony Liguori
2011-03-14 19:25 ` [Qemu-devel] " Luiz Capitulino
2011-03-14 20:18 ` Anthony Liguori
2011-03-14 20:33 ` Luiz Capitulino
2011-03-11 21:00 ` [Qemu-devel] [PATCH 10/11] json-streamer: limit the maximum recursion depth and maximum token count Anthony Liguori
2011-03-11 23:16 ` Michael Roth [this message]
2011-03-12 15:03 ` Anthony Liguori
2011-03-11 21:00 ` [Qemu-devel] [PATCH 11/11] json-parser: detect premature EOI Anthony Liguori
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D7AAD33.1000804@linux.vnet.ibm.com \
--to=mdroth@linux.vnet.ibm.com \
--cc=aliguori@us.ibm.com \
--cc=armbru@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=mdroth@us.ibm.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).