Commit 29c75ddd authored by Anthony Liguori's avatar Anthony Liguori
Browse files

json-streamer: limit the maximum recursion depth and maximum token count

parent 325601b4
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -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 ||
@@ -60,6 +65,17 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
        parser->emit(parser, parser->tokens);
        QDECREF(parser->tokens);
        parser->tokens = qlist_new();
    } 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);
        QDECREF(parser->tokens);
        parser->tokens = qlist_new();
    }
}

@@ -70,6 +86,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);
}