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