]> git.proxmox.com Git - mirror_qemu.git/blame - qobject/json-lexer.c
net: Clean up includes
[mirror_qemu.git] / qobject / json-lexer.c
CommitLineData
5ab8558d
AL
1/*
2 * JSON lexer
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
5ab8558d 14#include "qemu-common.h"
7b1b5d19 15#include "qapi/qmp/json-lexer.h"
d2ca7c0b 16#include <stdint.h>
5ab8558d 17
325601b4
AL
18#define MAX_TOKEN_SIZE (64ULL << 20)
19
5ab8558d
AL
20/*
21 * \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\"
22 * '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*'
23 * 0|([1-9][0-9]*(.[0-9]+)?([eE]([-+])?[0-9]+))
24 * [{}\[\],:]
25 * [a-z]+
26 *
27 */
28
29enum json_lexer_state {
b8d3b1da 30 IN_ERROR = 0, /* must really be 0, see json_lexer[] */
5ab8558d
AL
31 IN_DQ_UCODE3,
32 IN_DQ_UCODE2,
33 IN_DQ_UCODE1,
34 IN_DQ_UCODE0,
35 IN_DQ_STRING_ESCAPE,
36 IN_DQ_STRING,
37 IN_SQ_UCODE3,
38 IN_SQ_UCODE2,
39 IN_SQ_UCODE1,
40 IN_SQ_UCODE0,
41 IN_SQ_STRING_ESCAPE,
42 IN_SQ_STRING,
43 IN_ZERO,
44 IN_DIGITS,
45 IN_DIGIT,
46 IN_EXP_E,
47 IN_MANTISSA,
48 IN_MANTISSA_DIGITS,
49 IN_NONZERO_NUMBER,
50 IN_NEG_NONZERO_NUMBER,
51 IN_KEYWORD,
52 IN_ESCAPE,
53 IN_ESCAPE_L,
54 IN_ESCAPE_LL,
2c0d4b36
RT
55 IN_ESCAPE_I,
56 IN_ESCAPE_I6,
57 IN_ESCAPE_I64,
5ab8558d 58 IN_WHITESPACE,
5ab8558d
AL
59 IN_START,
60};
61
b8d3b1da
MA
62QEMU_BUILD_BUG_ON((int)JSON_MIN <= (int)IN_START);
63
5ab8558d
AL
64#define TERMINAL(state) [0 ... 0x7F] = (state)
65
f7c05274
PB
66/* Return whether TERMINAL is a terminal state and the transition to it
67 from OLD_STATE required lookahead. This happens whenever the table
68 below uses the TERMINAL macro. */
69#define TERMINAL_NEEDED_LOOKAHEAD(old_state, terminal) \
70 (json_lexer[(old_state)][0] == (terminal))
71
5ab8558d 72static const uint8_t json_lexer[][256] = {
b8d3b1da
MA
73 /* Relies on default initialization to IN_ERROR! */
74
5ab8558d
AL
75 /* double quote string */
76 [IN_DQ_UCODE3] = {
77 ['0' ... '9'] = IN_DQ_STRING,
78 ['a' ... 'f'] = IN_DQ_STRING,
79 ['A' ... 'F'] = IN_DQ_STRING,
80 },
81 [IN_DQ_UCODE2] = {
82 ['0' ... '9'] = IN_DQ_UCODE3,
83 ['a' ... 'f'] = IN_DQ_UCODE3,
84 ['A' ... 'F'] = IN_DQ_UCODE3,
85 },
86 [IN_DQ_UCODE1] = {
87 ['0' ... '9'] = IN_DQ_UCODE2,
88 ['a' ... 'f'] = IN_DQ_UCODE2,
89 ['A' ... 'F'] = IN_DQ_UCODE2,
90 },
91 [IN_DQ_UCODE0] = {
92 ['0' ... '9'] = IN_DQ_UCODE1,
93 ['a' ... 'f'] = IN_DQ_UCODE1,
94 ['A' ... 'F'] = IN_DQ_UCODE1,
95 },
96 [IN_DQ_STRING_ESCAPE] = {
97 ['b'] = IN_DQ_STRING,
98 ['f'] = IN_DQ_STRING,
99 ['n'] = IN_DQ_STRING,
100 ['r'] = IN_DQ_STRING,
101 ['t'] = IN_DQ_STRING,
1041ba7a
LC
102 ['/'] = IN_DQ_STRING,
103 ['\\'] = IN_DQ_STRING,
5ab8558d
AL
104 ['\''] = IN_DQ_STRING,
105 ['\"'] = IN_DQ_STRING,
106 ['u'] = IN_DQ_UCODE0,
107 },
108 [IN_DQ_STRING] = {
b011f619
MR
109 [1 ... 0xBF] = IN_DQ_STRING,
110 [0xC2 ... 0xF4] = IN_DQ_STRING,
5ab8558d 111 ['\\'] = IN_DQ_STRING_ESCAPE,
28e91a68 112 ['"'] = JSON_STRING,
5ab8558d
AL
113 },
114
115 /* single quote string */
116 [IN_SQ_UCODE3] = {
117 ['0' ... '9'] = IN_SQ_STRING,
118 ['a' ... 'f'] = IN_SQ_STRING,
119 ['A' ... 'F'] = IN_SQ_STRING,
120 },
121 [IN_SQ_UCODE2] = {
122 ['0' ... '9'] = IN_SQ_UCODE3,
123 ['a' ... 'f'] = IN_SQ_UCODE3,
124 ['A' ... 'F'] = IN_SQ_UCODE3,
125 },
126 [IN_SQ_UCODE1] = {
127 ['0' ... '9'] = IN_SQ_UCODE2,
128 ['a' ... 'f'] = IN_SQ_UCODE2,
129 ['A' ... 'F'] = IN_SQ_UCODE2,
130 },
131 [IN_SQ_UCODE0] = {
132 ['0' ... '9'] = IN_SQ_UCODE1,
133 ['a' ... 'f'] = IN_SQ_UCODE1,
134 ['A' ... 'F'] = IN_SQ_UCODE1,
135 },
136 [IN_SQ_STRING_ESCAPE] = {
137 ['b'] = IN_SQ_STRING,
138 ['f'] = IN_SQ_STRING,
139 ['n'] = IN_SQ_STRING,
140 ['r'] = IN_SQ_STRING,
141 ['t'] = IN_SQ_STRING,
d5932334
PB
142 ['/'] = IN_SQ_STRING,
143 ['\\'] = IN_SQ_STRING,
5ab8558d
AL
144 ['\''] = IN_SQ_STRING,
145 ['\"'] = IN_SQ_STRING,
146 ['u'] = IN_SQ_UCODE0,
147 },
148 [IN_SQ_STRING] = {
b011f619
MR
149 [1 ... 0xBF] = IN_SQ_STRING,
150 [0xC2 ... 0xF4] = IN_SQ_STRING,
5ab8558d 151 ['\\'] = IN_SQ_STRING_ESCAPE,
28e91a68 152 ['\''] = JSON_STRING,
5ab8558d
AL
153 },
154
155 /* Zero */
156 [IN_ZERO] = {
157 TERMINAL(JSON_INTEGER),
33d05394 158 ['0' ... '9'] = IN_ERROR,
5ab8558d
AL
159 ['.'] = IN_MANTISSA,
160 },
161
162 /* Float */
163 [IN_DIGITS] = {
164 TERMINAL(JSON_FLOAT),
165 ['0' ... '9'] = IN_DIGITS,
166 },
167
168 [IN_DIGIT] = {
169 ['0' ... '9'] = IN_DIGITS,
170 },
171
172 [IN_EXP_E] = {
173 ['-'] = IN_DIGIT,
174 ['+'] = IN_DIGIT,
175 ['0' ... '9'] = IN_DIGITS,
176 },
177
178 [IN_MANTISSA_DIGITS] = {
179 TERMINAL(JSON_FLOAT),
180 ['0' ... '9'] = IN_MANTISSA_DIGITS,
181 ['e'] = IN_EXP_E,
182 ['E'] = IN_EXP_E,
183 },
184
185 [IN_MANTISSA] = {
186 ['0' ... '9'] = IN_MANTISSA_DIGITS,
187 },
188
189 /* Number */
190 [IN_NONZERO_NUMBER] = {
191 TERMINAL(JSON_INTEGER),
192 ['0' ... '9'] = IN_NONZERO_NUMBER,
193 ['e'] = IN_EXP_E,
194 ['E'] = IN_EXP_E,
195 ['.'] = IN_MANTISSA,
196 },
197
198 [IN_NEG_NONZERO_NUMBER] = {
199 ['0'] = IN_ZERO,
200 ['1' ... '9'] = IN_NONZERO_NUMBER,
201 },
202
203 /* keywords */
204 [IN_KEYWORD] = {
205 TERMINAL(JSON_KEYWORD),
206 ['a' ... 'z'] = IN_KEYWORD,
207 },
208
209 /* whitespace */
210 [IN_WHITESPACE] = {
211 TERMINAL(JSON_SKIP),
212 [' '] = IN_WHITESPACE,
213 ['\t'] = IN_WHITESPACE,
214 ['\r'] = IN_WHITESPACE,
215 ['\n'] = IN_WHITESPACE,
216 },
217
5ab8558d 218 /* escape */
5ab8558d 219 [IN_ESCAPE_LL] = {
28e91a68 220 ['d'] = JSON_ESCAPE,
5ab8558d
AL
221 },
222
223 [IN_ESCAPE_L] = {
28e91a68 224 ['d'] = JSON_ESCAPE,
5ab8558d
AL
225 ['l'] = IN_ESCAPE_LL,
226 },
227
2c0d4b36 228 [IN_ESCAPE_I64] = {
28e91a68 229 ['d'] = JSON_ESCAPE,
2c0d4b36
RT
230 },
231
232 [IN_ESCAPE_I6] = {
233 ['4'] = IN_ESCAPE_I64,
234 },
235
236 [IN_ESCAPE_I] = {
237 ['6'] = IN_ESCAPE_I6,
238 },
239
5ab8558d 240 [IN_ESCAPE] = {
28e91a68
PB
241 ['d'] = JSON_ESCAPE,
242 ['i'] = JSON_ESCAPE,
243 ['p'] = JSON_ESCAPE,
244 ['s'] = JSON_ESCAPE,
245 ['f'] = JSON_ESCAPE,
5ab8558d 246 ['l'] = IN_ESCAPE_L,
2c0d4b36 247 ['I'] = IN_ESCAPE_I,
5ab8558d
AL
248 },
249
250 /* top level rule */
251 [IN_START] = {
252 ['"'] = IN_DQ_STRING,
253 ['\''] = IN_SQ_STRING,
254 ['0'] = IN_ZERO,
255 ['1' ... '9'] = IN_NONZERO_NUMBER,
256 ['-'] = IN_NEG_NONZERO_NUMBER,
c5461660
MA
257 ['{'] = JSON_LCURLY,
258 ['}'] = JSON_RCURLY,
259 ['['] = JSON_LSQUARE,
260 [']'] = JSON_RSQUARE,
261 [','] = JSON_COMMA,
262 [':'] = JSON_COLON,
5ab8558d
AL
263 ['a' ... 'z'] = IN_KEYWORD,
264 ['%'] = IN_ESCAPE,
265 [' '] = IN_WHITESPACE,
266 ['\t'] = IN_WHITESPACE,
267 ['\r'] = IN_WHITESPACE,
268 ['\n'] = IN_WHITESPACE,
269 },
270};
271
272void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
273{
274 lexer->emit = func;
275 lexer->state = IN_START;
d2ca7c0b 276 lexer->token = g_string_sized_new(3);
03308f6c 277 lexer->x = lexer->y = 0;
5ab8558d
AL
278}
279
bd3924a3 280static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush)
5ab8558d 281{
f7c05274
PB
282 int char_consumed, new_state;
283
5ab8558d
AL
284 lexer->x++;
285 if (ch == '\n') {
286 lexer->x = 0;
287 lexer->y++;
288 }
289
f7c05274 290 do {
b8d3b1da 291 assert(lexer->state <= ARRAY_SIZE(json_lexer));
f7c05274
PB
292 new_state = json_lexer[lexer->state][(uint8_t)ch];
293 char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state);
294 if (char_consumed) {
d2ca7c0b 295 g_string_append_c(lexer->token, ch);
f7c05274 296 }
5ab8558d 297
f7c05274 298 switch (new_state) {
c5461660
MA
299 case JSON_LCURLY:
300 case JSON_RCURLY:
301 case JSON_LSQUARE:
302 case JSON_RSQUARE:
303 case JSON_COLON:
304 case JSON_COMMA:
f7c05274
PB
305 case JSON_ESCAPE:
306 case JSON_INTEGER:
307 case JSON_FLOAT:
308 case JSON_KEYWORD:
309 case JSON_STRING:
310 lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y);
0b0404bf 311 /* fall through */
f7c05274 312 case JSON_SKIP:
d2ca7c0b 313 g_string_truncate(lexer->token, 0);
f7c05274
PB
314 new_state = IN_START;
315 break;
33d05394 316 case IN_ERROR:
b011f619
MR
317 /* XXX: To avoid having previous bad input leaving the parser in an
318 * unresponsive state where we consume unpredictable amounts of
319 * subsequent "good" input, percolate this error state up to the
320 * tokenizer/parser by forcing a NULL object to be emitted, then
321 * reset state.
322 *
323 * Also note that this handling is required for reliable channel
324 * negotiation between QMP and the guest agent, since chr(0xFF)
325 * is placed at the beginning of certain events to ensure proper
326 * delivery when the channel is in an unknown state. chr(0xFF) is
327 * never a valid ASCII/UTF-8 sequence, so this should reliably
328 * induce an error/flush state.
329 */
330 lexer->emit(lexer, lexer->token, JSON_ERROR, lexer->x, lexer->y);
d2ca7c0b 331 g_string_truncate(lexer->token, 0);
529a0ef5 332 new_state = IN_START;
b011f619
MR
333 lexer->state = new_state;
334 return 0;
f7c05274
PB
335 default:
336 break;
337 }
338 lexer->state = new_state;
bd3924a3 339 } while (!char_consumed && !flush);
325601b4
AL
340
341 /* Do not let a single token grow to an arbitrarily large size,
342 * this is a security consideration.
343 */
d2ca7c0b 344 if (lexer->token->len > MAX_TOKEN_SIZE) {
325601b4 345 lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y);
d2ca7c0b 346 g_string_truncate(lexer->token, 0);
325601b4
AL
347 lexer->state = IN_START;
348 }
349
5ab8558d
AL
350 return 0;
351}
352
353int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size)
354{
355 size_t i;
356
357 for (i = 0; i < size; i++) {
358 int err;
359
bd3924a3 360 err = json_lexer_feed_char(lexer, buffer[i], false);
5ab8558d
AL
361 if (err < 0) {
362 return err;
363 }
364 }
365
366 return 0;
367}
368
369int json_lexer_flush(JSONLexer *lexer)
370{
b011f619 371 return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0, true);
5ab8558d
AL
372}
373
374void json_lexer_destroy(JSONLexer *lexer)
375{
d2ca7c0b 376 g_string_free(lexer->token, true);
5ab8558d 377}