json-streamer.c (3677B)
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 "qapi/error.h" 16#include "json-parser-int.h" 17 18#define MAX_TOKEN_SIZE (64ULL << 20) 19#define MAX_TOKEN_COUNT (2ULL << 20) 20#define MAX_NESTING (1 << 10) 21 22static void json_message_free_tokens(JSONMessageParser *parser) 23{ 24 JSONToken *token; 25 26 while ((token = g_queue_pop_head(&parser->tokens))) { 27 g_free(token); 28 } 29} 30 31void 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 QObject *json = NULL; 36 Error *err = NULL; 37 JSONToken *token; 38 39 switch (type) { 40 case JSON_LCURLY: 41 parser->brace_count++; 42 break; 43 case JSON_RCURLY: 44 parser->brace_count--; 45 break; 46 case JSON_LSQUARE: 47 parser->bracket_count++; 48 break; 49 case JSON_RSQUARE: 50 parser->bracket_count--; 51 break; 52 case JSON_ERROR: 53 error_setg(&err, "JSON parse error, stray '%s'", input->str); 54 goto out_emit; 55 case JSON_END_OF_INPUT: 56 if (g_queue_is_empty(&parser->tokens)) { 57 return; 58 } 59 json = json_parser_parse(&parser->tokens, parser->ap, &err); 60 goto out_emit; 61 default: 62 break; 63 } 64 65 /* 66 * Security consideration, we limit total memory allocated per object 67 * and the maximum recursion depth that a message can force. 68 */ 69 if (parser->token_size + input->len + 1 > MAX_TOKEN_SIZE) { 70 error_setg(&err, "JSON token size limit exceeded"); 71 goto out_emit; 72 } 73 if (g_queue_get_length(&parser->tokens) + 1 > MAX_TOKEN_COUNT) { 74 error_setg(&err, "JSON token count limit exceeded"); 75 goto out_emit; 76 } 77 if (parser->bracket_count + parser->brace_count > MAX_NESTING) { 78 error_setg(&err, "JSON nesting depth limit exceeded"); 79 goto out_emit; 80 } 81 82 token = json_token(type, x, y, input); 83 parser->token_size += input->len; 84 85 g_queue_push_tail(&parser->tokens, token); 86 87 if ((parser->brace_count > 0 || parser->bracket_count > 0) 88 && parser->brace_count >= 0 && parser->bracket_count >= 0) { 89 return; 90 } 91 92 json = json_parser_parse(&parser->tokens, parser->ap, &err); 93 94out_emit: 95 parser->brace_count = 0; 96 parser->bracket_count = 0; 97 json_message_free_tokens(parser); 98 parser->token_size = 0; 99 parser->emit(parser->opaque, json, err); 100} 101 102void json_message_parser_init(JSONMessageParser *parser, 103 void (*emit)(void *opaque, QObject *json, 104 Error *err), 105 void *opaque, va_list *ap) 106{ 107 parser->emit = emit; 108 parser->opaque = opaque; 109 parser->ap = ap; 110 parser->brace_count = 0; 111 parser->bracket_count = 0; 112 g_queue_init(&parser->tokens); 113 parser->token_size = 0; 114 115 json_lexer_init(&parser->lexer, !!ap); 116} 117 118void json_message_parser_feed(JSONMessageParser *parser, 119 const char *buffer, size_t size) 120{ 121 json_lexer_feed(&parser->lexer, buffer, size); 122} 123 124void json_message_parser_flush(JSONMessageParser *parser) 125{ 126 json_lexer_flush(&parser->lexer); 127 assert(g_queue_is_empty(&parser->tokens)); 128} 129 130void json_message_parser_destroy(JSONMessageParser *parser) 131{ 132 json_lexer_destroy(&parser->lexer); 133 json_message_free_tokens(parser); 134}