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