]> Git Repo - qemu.git/blob - qobject/json-streamer.c
json: Don't pass null @tokens to json_parser_parse()
[qemu.git] / qobject / json-streamer.c
1 /*
2  * JSON streaming support
3  *
4  * Copyright IBM, Corp. 2009
5  *
6  * Authors:
7  *  Anthony Liguori   <[email protected]>
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-parser.h"
18 #include "qapi/qmp/json-streamer.h"
19
20 #define MAX_TOKEN_SIZE (64ULL << 20)
21 #define MAX_TOKEN_COUNT (2ULL << 20)
22 #define MAX_NESTING (1ULL << 10)
23
24 static void json_message_free_token(void *token, void *opaque)
25 {
26     g_free(token);
27 }
28
29 static void json_message_free_tokens(JSONMessageParser *parser)
30 {
31     if (parser->tokens) {
32         g_queue_foreach(parser->tokens, json_message_free_token, NULL);
33         g_queue_free(parser->tokens);
34         parser->tokens = NULL;
35     }
36 }
37
38 void json_message_process_token(JSONLexer *lexer, GString *input,
39                                 JSONTokenType type, int x, int y)
40 {
41     JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer);
42     QObject *json = NULL;
43     Error *err = NULL;
44     JSONToken *token;
45
46     switch (type) {
47     case JSON_LCURLY:
48         parser->brace_count++;
49         break;
50     case JSON_RCURLY:
51         parser->brace_count--;
52         break;
53     case JSON_LSQUARE:
54         parser->bracket_count++;
55         break;
56     case JSON_RSQUARE:
57         parser->bracket_count--;
58         break;
59     default:
60         break;
61     }
62
63     token = g_malloc(sizeof(JSONToken) + input->len + 1);
64     token->type = type;
65     memcpy(token->str, input->str, input->len);
66     token->str[input->len] = 0;
67     token->x = x;
68     token->y = y;
69
70     parser->token_size += input->len;
71
72     g_queue_push_tail(parser->tokens, token);
73
74     if (type == JSON_ERROR) {
75         goto out_emit;
76     }
77
78     if (parser->brace_count < 0 ||
79         parser->bracket_count < 0 ||
80         (parser->brace_count == 0 &&
81          parser->bracket_count == 0)) {
82         json = json_parser_parse(parser->tokens, parser->ap, &err);
83         parser->tokens = NULL;
84         goto out_emit;
85     }
86
87     if (parser->token_size > MAX_TOKEN_SIZE ||
88                g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT ||
89                parser->bracket_count + parser->brace_count > MAX_NESTING) {
90         /* Security consideration, we limit total memory allocated per object
91          * and the maximum recursion depth that a message can force.
92          */
93         goto out_emit;
94     }
95
96     return;
97
98 out_emit:
99     parser->brace_count = 0;
100     parser->bracket_count = 0;
101     json_message_free_tokens(parser);
102     parser->tokens = g_queue_new();
103     parser->token_size = 0;
104     parser->emit(parser->opaque, json, err);
105 }
106
107 void json_message_parser_init(JSONMessageParser *parser,
108                               void (*emit)(void *opaque, QObject *json,
109                                            Error *err),
110                               void *opaque, va_list *ap)
111 {
112     parser->emit = emit;
113     parser->opaque = opaque;
114     parser->ap = ap;
115     parser->brace_count = 0;
116     parser->bracket_count = 0;
117     parser->tokens = g_queue_new();
118     parser->token_size = 0;
119
120     json_lexer_init(&parser->lexer);
121 }
122
123 void json_message_parser_feed(JSONMessageParser *parser,
124                              const char *buffer, size_t size)
125 {
126     json_lexer_feed(&parser->lexer, buffer, size);
127 }
128
129 void json_message_parser_flush(JSONMessageParser *parser)
130 {
131     json_lexer_flush(&parser->lexer);
132 }
133
134 void json_message_parser_destroy(JSONMessageParser *parser)
135 {
136     json_lexer_destroy(&parser->lexer);
137     json_message_free_tokens(parser);
138 }
This page took 0.028375 seconds and 4 git commands to generate.