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