qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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 
     22 static 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 
     31 void 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 
     94 out_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 
    102 void 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 
    118 void json_message_parser_feed(JSONMessageParser *parser,
    119                              const char *buffer, size_t size)
    120 {
    121     json_lexer_feed(&parser->lexer, buffer, size);
    122 }
    123 
    124 void json_message_parser_flush(JSONMessageParser *parser)
    125 {
    126     json_lexer_flush(&parser->lexer);
    127     assert(g_queue_is_empty(&parser->tokens));
    128 }
    129 
    130 void json_message_parser_destroy(JSONMessageParser *parser)
    131 {
    132     json_lexer_destroy(&parser->lexer);
    133     json_message_free_tokens(parser);
    134 }