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