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