Home | History | Annotate | Download | only in qobject
      1 /*
      2  * JSON streaming support
      3  *
      4  * Copyright IBM, Corp. 2009
      5  *
      6  * Authors:
      7  *  Anthony Liguori   <aliguori (at) 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 "qapi/qmp/qlist.h"
     15 #include "qapi/qmp/qint.h"
     16 #include "qapi/qmp/qdict.h"
     17 #include "qemu-common.h"
     18 #include "qapi/qmp/json-lexer.h"
     19 #include "qapi/qmp/json-streamer.h"
     20 
     21 #define MAX_TOKEN_SIZE (64ULL << 20)
     22 #define MAX_NESTING (1ULL << 10)
     23 
     24 static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTokenType type, int x, int y)
     25 {
     26     JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
     27     QDict *dict;
     28 
     29     if (type == JSON_OPERATOR) {
     30         switch (qstring_get_str(token)[0]) {
     31         case '{':
     32             parser->brace_count++;
     33             break;
     34         case '}':
     35             parser->brace_count--;
     36             break;
     37         case '[':
     38             parser->bracket_count++;
     39             break;
     40         case ']':
     41             parser->bracket_count--;
     42             break;
     43         default:
     44             break;
     45         }
     46     }
     47 
     48     dict = qdict_new();
     49     qdict_put(dict, "type", qint_from_int(type));
     50     QINCREF(token);
     51     qdict_put(dict, "token", token);
     52     qdict_put(dict, "x", qint_from_int(x));
     53     qdict_put(dict, "y", qint_from_int(y));
     54 
     55     parser->token_size += token->length;
     56 
     57     qlist_append(parser->tokens, dict);
     58 
     59     if (type == JSON_ERROR) {
     60         goto out_emit_bad;
     61     } else if (parser->brace_count < 0 ||
     62         parser->bracket_count < 0 ||
     63         (parser->brace_count == 0 &&
     64          parser->bracket_count == 0)) {
     65         goto out_emit;
     66     } else if (parser->token_size > MAX_TOKEN_SIZE ||
     67                parser->bracket_count > MAX_NESTING ||
     68                parser->brace_count > MAX_NESTING) {
     69         /* Security consideration, we limit total memory allocated per object
     70          * and the maximum recursion depth that a message can force.
     71          */
     72         goto out_emit;
     73     }
     74 
     75     return;
     76 
     77 out_emit_bad:
     78     /* clear out token list and tell the parser to emit and error
     79      * indication by passing it a NULL list
     80      */
     81     QDECREF(parser->tokens);
     82     parser->tokens = NULL;
     83 out_emit:
     84     /* send current list of tokens to parser and reset tokenizer */
     85     parser->brace_count = 0;
     86     parser->bracket_count = 0;
     87     parser->emit(parser, parser->tokens);
     88     if (parser->tokens) {
     89         QDECREF(parser->tokens);
     90     }
     91     parser->tokens = qlist_new();
     92     parser->token_size = 0;
     93 }
     94 
     95 void json_message_parser_init(JSONMessageParser *parser,
     96                               void (*func)(JSONMessageParser *, QList *))
     97 {
     98     parser->emit = func;
     99     parser->brace_count = 0;
    100     parser->bracket_count = 0;
    101     parser->tokens = qlist_new();
    102     parser->token_size = 0;
    103 
    104     json_lexer_init(&parser->lexer, json_message_process_token);
    105 }
    106 
    107 int json_message_parser_feed(JSONMessageParser *parser,
    108                              const char *buffer, size_t size)
    109 {
    110     return json_lexer_feed(&parser->lexer, buffer, size);
    111 }
    112 
    113 int json_message_parser_flush(JSONMessageParser *parser)
    114 {
    115     return json_lexer_flush(&parser->lexer);
    116 }
    117 
    118 void json_message_parser_destroy(JSONMessageParser *parser)
    119 {
    120     json_lexer_destroy(&parser->lexer);
    121     QDECREF(parser->tokens);
    122 }
    123