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 43 switch (type) { 44 case JSON_LCURLY: 45 parser->brace_count++; 46 break; 47 case JSON_RCURLY: 48 parser->brace_count--; 49 break; 50 case JSON_LSQUARE: 51 parser->bracket_count++; 52 break; 53 case JSON_RSQUARE: 54 parser->bracket_count--; 55 break; 56 default: 57 break; 58 } 59 60 token = g_malloc(sizeof(JSONToken) + input->len + 1); 61 token->type = type; 62 memcpy(token->str, input->str, input->len); 63 token->str[input->len] = 0; 64 token->x = x; 65 token->y = y; 66 67 parser->token_size += input->len; 68 69 g_queue_push_tail(parser->tokens, token); 70 71 if (type == JSON_ERROR) { 72 goto out_emit_bad; 73 } else if (parser->brace_count < 0 || 74 parser->bracket_count < 0 || 75 (parser->brace_count == 0 && 76 parser->bracket_count == 0)) { 77 goto out_emit; 78 } else if (parser->token_size > MAX_TOKEN_SIZE || 79 g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT || 80 parser->bracket_count + parser->brace_count > MAX_NESTING) { 81 /* Security consideration, we limit total memory allocated per object 82 * and the maximum recursion depth that a message can force. 83 */ 84 goto out_emit_bad; 85 } 86 87 return; 88 89 out_emit_bad: 90 /* 91 * Clear out token list and tell the parser to emit an error 92 * indication by passing it a NULL list 93 */ 94 json_message_free_tokens(parser); 95 out_emit: 96 /* send current list of tokens to parser and reset tokenizer */ 97 parser->brace_count = 0; 98 parser->bracket_count = 0; 99 /* parser->emit takes ownership of parser->tokens. */ 100 parser->emit(parser, parser->tokens); 101 parser->tokens = g_queue_new(); 102 parser->token_size = 0; 103 } 104 105 void json_message_parser_init(JSONMessageParser *parser, 106 void (*func)(JSONMessageParser *, GQueue *)) 107 { 108 parser->emit = func; 109 parser->brace_count = 0; 110 parser->bracket_count = 0; 111 parser->tokens = g_queue_new(); 112 parser->token_size = 0; 113 114 json_lexer_init(&parser->lexer, json_message_process_token); 115 } 116 117 int json_message_parser_feed(JSONMessageParser *parser, 118 const char *buffer, size_t size) 119 { 120 return json_lexer_feed(&parser->lexer, buffer, size); 121 } 122 123 int json_message_parser_flush(JSONMessageParser *parser) 124 { 125 return json_lexer_flush(&parser->lexer); 126 } 127 128 void json_message_parser_destroy(JSONMessageParser *parser) 129 { 130 json_lexer_destroy(&parser->lexer); 131 json_message_free_tokens(parser); 132 } 133