cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

json-streamer.c (3677B)


      1/*
      2 * JSON streaming support
      3 *
      4 * Copyright IBM, Corp. 2009
      5 *
      6 * Authors:
      7 *  Anthony Liguori   <aliguori@us.ibm.com>
      8 *
      9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
     10 * See the COPYING.LIB file in the top-level directory.
     11 *
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "qapi/error.h"
     16#include "json-parser-int.h"
     17
     18#define MAX_TOKEN_SIZE (64ULL << 20)
     19#define MAX_TOKEN_COUNT (2ULL << 20)
     20#define MAX_NESTING (1 << 10)
     21
     22static void json_message_free_tokens(JSONMessageParser *parser)
     23{
     24    JSONToken *token;
     25
     26    while ((token = g_queue_pop_head(&parser->tokens))) {
     27        g_free(token);
     28    }
     29}
     30
     31void json_message_process_token(JSONLexer *lexer, GString *input,
     32                                JSONTokenType type, int x, int y)
     33{
     34    JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
     35    QObject *json = NULL;
     36    Error *err = NULL;
     37    JSONToken *token;
     38
     39    switch (type) {
     40    case JSON_LCURLY:
     41        parser->brace_count++;
     42        break;
     43    case JSON_RCURLY:
     44        parser->brace_count--;
     45        break;
     46    case JSON_LSQUARE:
     47        parser->bracket_count++;
     48        break;
     49    case JSON_RSQUARE:
     50        parser->bracket_count--;
     51        break;
     52    case JSON_ERROR:
     53        error_setg(&err, "JSON parse error, stray '%s'", input->str);
     54        goto out_emit;
     55    case JSON_END_OF_INPUT:
     56        if (g_queue_is_empty(&parser->tokens)) {
     57            return;
     58        }
     59        json = json_parser_parse(&parser->tokens, parser->ap, &err);
     60        goto out_emit;
     61    default:
     62        break;
     63    }
     64
     65    /*
     66     * Security consideration, we limit total memory allocated per object
     67     * and the maximum recursion depth that a message can force.
     68     */
     69    if (parser->token_size + input->len + 1 > MAX_TOKEN_SIZE) {
     70        error_setg(&err, "JSON token size limit exceeded");
     71        goto out_emit;
     72    }
     73    if (g_queue_get_length(&parser->tokens) + 1 > MAX_TOKEN_COUNT) {
     74        error_setg(&err, "JSON token count limit exceeded");
     75        goto out_emit;
     76    }
     77    if (parser->bracket_count + parser->brace_count > MAX_NESTING) {
     78        error_setg(&err, "JSON nesting depth limit exceeded");
     79        goto out_emit;
     80    }
     81
     82    token = json_token(type, x, y, input);
     83    parser->token_size += input->len;
     84
     85    g_queue_push_tail(&parser->tokens, token);
     86
     87    if ((parser->brace_count > 0 || parser->bracket_count > 0)
     88        && parser->brace_count >= 0 && parser->bracket_count >= 0) {
     89        return;
     90    }
     91
     92    json = json_parser_parse(&parser->tokens, parser->ap, &err);
     93
     94out_emit:
     95    parser->brace_count = 0;
     96    parser->bracket_count = 0;
     97    json_message_free_tokens(parser);
     98    parser->token_size = 0;
     99    parser->emit(parser->opaque, json, err);
    100}
    101
    102void json_message_parser_init(JSONMessageParser *parser,
    103                              void (*emit)(void *opaque, QObject *json,
    104                                           Error *err),
    105                              void *opaque, va_list *ap)
    106{
    107    parser->emit = emit;
    108    parser->opaque = opaque;
    109    parser->ap = ap;
    110    parser->brace_count = 0;
    111    parser->bracket_count = 0;
    112    g_queue_init(&parser->tokens);
    113    parser->token_size = 0;
    114
    115    json_lexer_init(&parser->lexer, !!ap);
    116}
    117
    118void json_message_parser_feed(JSONMessageParser *parser,
    119                             const char *buffer, size_t size)
    120{
    121    json_lexer_feed(&parser->lexer, buffer, size);
    122}
    123
    124void json_message_parser_flush(JSONMessageParser *parser)
    125{
    126    json_lexer_flush(&parser->lexer);
    127    assert(g_queue_is_empty(&parser->tokens));
    128}
    129
    130void json_message_parser_destroy(JSONMessageParser *parser)
    131{
    132    json_lexer_destroy(&parser->lexer);
    133    json_message_free_tokens(parser);
    134}