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