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