Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/json.h"
7 : :
8 : : #include "spdk_internal/utf.h"
9 : :
10 : : #define SPDK_JSON_MAX_NESTING_DEPTH 64
11 : :
12 : : static int
13 : 640 : hex_value(uint8_t c)
14 : : {
15 : : #define V(x, y) [x] = y + 1
16 : : static const int8_t val[256] = {
17 : : V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
18 : : V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
19 : : V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
20 : : V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
21 : : };
22 : : #undef V
23 : :
24 [ # # # # : 640 : return val[c] - 1;
# # # # ]
25 : : }
26 : :
27 : : static int
28 : 200 : json_decode_string_escape_unicode(uint8_t **strp, uint8_t *buf_end, uint8_t *out)
29 : : {
30 [ # # ]: 200 : uint8_t *str = *strp;
31 : : int v0, v1, v2, v3;
32 : : uint32_t val;
33 : 200 : uint32_t surrogate_high = 0;
34 : 45 : int rc;
35 : 182 : decode:
36 : : /* \uXXXX */
37 [ + + # # ]: 236 : assert(buf_end > str);
38 : :
39 [ + + # # : 236 : if (*str++ != '\\') { return SPDK_JSON_PARSE_INVALID; }
# # ]
40 [ + + ]: 228 : if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
41 : :
42 [ + + # # : 224 : if (*str++ != 'u') { return SPDK_JSON_PARSE_INVALID; }
# # ]
43 [ + + ]: 184 : if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
44 : :
45 [ + + # # : 176 : if ((v3 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
# # ]
46 [ + + ]: 172 : if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
47 : :
48 [ + + # # : 164 : if ((v2 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
# # ]
49 [ + + ]: 160 : if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
50 : :
51 [ + + # # : 156 : if ((v1 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
# # ]
52 [ + + ]: 152 : if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
53 : :
54 [ + + # # : 144 : if ((v0 = hex_value(*str++)) < 0) { return SPDK_JSON_PARSE_INVALID; }
# # ]
55 [ + + ]: 136 : if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
56 : :
57 [ - + - + : 132 : val = v0 | (v1 << 4) | (v2 << 8) | (v3 << 12);
- + # # #
# # # ]
58 : :
59 [ + + ]: 132 : if (surrogate_high) {
60 : : /* We already parsed the high surrogate, so this should be the low part. */
61 [ + + ]: 12 : if (!utf16_valid_surrogate_low(val)) {
62 : 4 : return SPDK_JSON_PARSE_INVALID;
63 : : }
64 : :
65 : : /* Convert UTF-16 surrogate pair into codepoint and fall through to utf8_encode. */
66 : 8 : val = utf16_decode_surrogate_pair(surrogate_high, val);
67 [ + + ]: 122 : } else if (utf16_valid_surrogate_high(val)) {
68 : 36 : surrogate_high = val;
69 : :
70 : : /*
71 : : * We parsed a \uXXXX sequence that decoded to the first half of a
72 : : * UTF-16 surrogate pair, so it must be immediately followed by another
73 : : * \uXXXX escape.
74 : : *
75 : : * Loop around to get the low half of the surrogate pair.
76 : : */
77 [ + + ]: 36 : if (buf_end == str) { return SPDK_JSON_PARSE_INCOMPLETE; }
78 : 36 : goto decode;
79 [ + + ]: 84 : } else if (utf16_valid_surrogate_low(val)) {
80 : : /*
81 : : * We found the second half of surrogate pair without the first half;
82 : : * this is an invalid encoding.
83 : : */
84 : 16 : return SPDK_JSON_PARSE_INVALID;
85 : : }
86 : :
87 : : /*
88 : : * Convert Unicode escape (or surrogate pair) to UTF-8 in place.
89 : : *
90 : : * This is safe (will not write beyond the buffer) because the \uXXXX sequence is 6 bytes
91 : : * (or 12 bytes for surrogate pairs), and the longest possible UTF-8 encoding of a
92 : : * single codepoint is 4 bytes.
93 : : */
94 [ + + ]: 76 : if (out) {
95 : 38 : rc = utf8_encode_unsafe(out, val);
96 : 7 : } else {
97 : 38 : rc = utf8_codepoint_len(val);
98 : : }
99 [ + + ]: 76 : if (rc < 0) {
100 : 0 : return SPDK_JSON_PARSE_INVALID;
101 : : }
102 : :
103 [ # # ]: 76 : *strp = str; /* update input pointer */
104 : 76 : return rc; /* return number of bytes decoded */
105 : 45 : }
106 : :
107 : : static int
108 : 310 : json_decode_string_escape_twochar(uint8_t **strp, uint8_t *buf_end, uint8_t *out)
109 : : {
110 : : static const uint8_t escapes[256] = {
111 : : ['b'] = '\b',
112 : : ['f'] = '\f',
113 : : ['n'] = '\n',
114 : : ['r'] = '\r',
115 : : ['t'] = '\t',
116 : : ['/'] = '/',
117 : : ['"'] = '"',
118 : : ['\\'] = '\\',
119 : : };
120 [ # # ]: 310 : uint8_t *str = *strp;
121 : : uint8_t c;
122 : :
123 [ + + # # ]: 310 : assert(buf_end > str);
124 [ - + ]: 310 : if (buf_end - str < 2) {
125 : 0 : return SPDK_JSON_PARSE_INCOMPLETE;
126 : : }
127 : :
128 [ - + # # : 310 : assert(str[0] == '\\');
# # # # ]
129 : :
130 [ # # # # : 310 : c = escapes[str[1]];
# # # # #
# ]
131 [ + + ]: 310 : if (c) {
132 [ + + ]: 110 : if (out) {
133 [ # # ]: 51 : *out = c;
134 : 11 : }
135 [ # # # # ]: 110 : *strp += 2; /* consumed two bytes */
136 : 110 : return 1; /* produced one byte */
137 : : }
138 : :
139 : 200 : return SPDK_JSON_PARSE_INVALID;
140 : 69 : }
141 : :
142 : : /*
143 : : * Decode JSON string backslash escape.
144 : : * \param strp pointer to pointer to first character of escape (the backslash).
145 : : * *strp is also advanced to indicate how much input was consumed.
146 : : *
147 : : * \return Number of bytes appended to out
148 : : */
149 : : static int
150 : 310 : json_decode_string_escape(uint8_t **strp, uint8_t *buf_end, uint8_t *out)
151 : : {
152 : : int rc;
153 : :
154 : 310 : rc = json_decode_string_escape_twochar(strp, buf_end, out);
155 [ + + ]: 310 : if (rc > 0) {
156 : 110 : return rc;
157 : : }
158 : :
159 : 200 : return json_decode_string_escape_unicode(strp, buf_end, out);
160 : 69 : }
161 : :
162 : : /*
163 : : * Decode JSON string in place.
164 : : *
165 : : * \param str_start Pointer to the beginning of the string (the opening " character).
166 : : *
167 : : * \return Number of bytes in decoded string (beginning from start).
168 : : */
169 : : static int
170 : 1148106 : json_decode_string(uint8_t *str_start, uint8_t *buf_end, uint8_t **str_end, uint32_t flags)
171 : : {
172 : 1148106 : uint8_t *str = str_start;
173 [ + - ]: 1148106 : uint8_t *out = str_start + 1; /* Decode string in place (skip the initial quote) */
174 : : int rc;
175 : :
176 [ + + ]: 1148106 : if (buf_end - str_start < 2) {
177 : : /*
178 : : * Shortest valid string (the empty string) is two bytes (""),
179 : : * so this can't possibly be valid
180 : : */
181 [ # # ]: 24 : *str_end = str;
182 : 24 : return SPDK_JSON_PARSE_INCOMPLETE;
183 : : }
184 : :
185 [ + + + - : 1148082 : if (*str++ != '"') {
- + ]
186 [ # # ]: 0 : *str_end = str;
187 : 0 : return SPDK_JSON_PARSE_INVALID;
188 : : }
189 : :
190 [ + + ]: 11999224 : while (str < buf_end) {
191 [ + + + - : 11999096 : if (str[0] == '"') {
+ + ]
192 : : /*
193 : : * End of string.
194 : : * Update str_end to point at next input byte and return output length.
195 : : */
196 [ + - + - ]: 1147510 : *str_end = str + 1;
197 [ + - ]: 1147510 : return out - str_start - 1;
198 [ + + + - : 10851586 : } else if (str[0] == '\\') {
- + ]
199 : 379 : rc = json_decode_string_escape(&str, buf_end,
200 [ + + ]: 310 : flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE ? out : NULL);
201 [ + + # # ]: 310 : assert(rc != 0);
202 [ + + ]: 310 : if (rc < 0) {
203 [ # # ]: 124 : *str_end = str;
204 : 124 : return rc;
205 : : }
206 [ # # ]: 186 : out += rc;
207 [ + + + - : 10851314 : } else if (str[0] <= 0x1f) {
+ - ]
208 : : /* control characters must be escaped */
209 [ # # ]: 140 : *str_end = str;
210 : 140 : return SPDK_JSON_PARSE_INVALID;
211 : : } else {
212 : 10851136 : rc = utf8_valid(str, buf_end);
213 [ + + ]: 10851136 : if (rc == 0) {
214 [ # # ]: 0 : *str_end = str;
215 : 0 : return SPDK_JSON_PARSE_INCOMPLETE;
216 [ + + ]: 10851136 : } else if (rc < 0) {
217 [ # # ]: 180 : *str_end = str;
218 : 180 : return SPDK_JSON_PARSE_INVALID;
219 : : }
220 : :
221 [ + - + + : 10850956 : if (out && out != str && (flags & SPDK_JSON_PARSE_FLAG_DECODE_IN_PLACE)) {
+ + ]
222 [ - + - + ]: 154 : memmove(out, str, rc);
223 : 6 : }
224 [ + - ]: 10850956 : out += rc;
225 [ + - ]: 10850956 : str += rc;
226 : : }
227 : : }
228 : :
229 : : /* If execution gets here, we ran out of buffer. */
230 [ # # ]: 128 : *str_end = str;
231 : 128 : return SPDK_JSON_PARSE_INCOMPLETE;
232 : 58295 : }
233 : :
234 : : static int
235 : 229664 : json_valid_number(uint8_t *start, uint8_t *buf_end)
236 : : {
237 : 229664 : uint8_t *p = start;
238 : : uint8_t c;
239 : :
240 [ - + ]: 229664 : if (p >= buf_end) { return -1; }
241 : :
242 [ + - + - ]: 229664 : c = *p++;
243 [ + + + + ]: 229664 : if (c >= '1' && c <= '9') { goto num_int_digits; }
244 [ + + ]: 72880 : if (c == '0') { goto num_frac_or_exp; }
245 [ + - ]: 178 : if (c == '-') { goto num_int_first_digit; }
246 [ # # ]: 0 : p--;
247 : 0 : goto done_invalid;
248 : :
249 : 158 : num_int_first_digit:
250 [ + + ]: 178 : if (spdk_likely(p != buf_end)) {
251 [ # # # # ]: 174 : c = *p++;
252 [ + + ]: 174 : if (c == '0') { goto num_frac_or_exp; }
253 [ + + + + ]: 142 : if (c >= '1' && c <= '9') { goto num_int_digits; }
254 [ # # ]: 4 : p--;
255 : 1 : }
256 : 8 : goto done_invalid;
257 : :
258 : 147380 : num_int_digits:
259 [ + + ]: 361662 : if (spdk_likely(p != buf_end)) {
260 [ + - + - ]: 361630 : c = *p++;
261 [ + + + + ]: 361630 : if (c >= '0' && c <= '9') { goto num_int_digits; }
262 [ + + ]: 156890 : if (c == '.') { goto num_frac_first_digit; }
263 [ + + + + ]: 156714 : if (c == 'e' || c == 'E') { goto num_exp_sign; }
264 [ + - ]: 156666 : p--;
265 : 9478 : }
266 : 156698 : goto done_valid;
267 : :
268 : 65190 : num_frac_or_exp:
269 [ + + ]: 72734 : if (spdk_likely(p != buf_end)) {
270 [ + - + - ]: 72694 : c = *p++;
271 [ - + ]: 72694 : if (c == '.') { goto num_frac_first_digit; }
272 [ + + - + ]: 72694 : if (c == 'e' || c == 'E') { goto num_exp_sign; }
273 [ + - ]: 72654 : p--;
274 : 7524 : }
275 : 72694 : goto done_valid;
276 : :
277 : 132 : num_frac_first_digit:
278 [ + + ]: 176 : if (spdk_likely(p != buf_end)) {
279 [ # # # # ]: 168 : c = *p++;
280 [ + + + + ]: 168 : if (c >= '0' && c <= '9') { goto num_frac_digits; }
281 [ # # ]: 8 : p--;
282 : 2 : }
283 : 16 : goto done_invalid;
284 : :
285 : 492 : num_frac_digits:
286 [ + + ]: 656 : if (spdk_likely(p != buf_end)) {
287 [ # # # # ]: 616 : c = *p++;
288 [ + + + + ]: 616 : if (c >= '0' && c <= '9') { goto num_frac_digits; }
289 [ + + - + ]: 120 : if (c == 'e' || c == 'E') { goto num_exp_sign; }
290 [ # # ]: 56 : p--;
291 : 14 : }
292 : 96 : goto done_valid;
293 : :
294 : 114 : num_exp_sign:
295 [ + + ]: 152 : if (spdk_likely(p != buf_end)) {
296 [ # # # # ]: 152 : c = *p++;
297 [ + + + + ]: 152 : if (c >= '0' && c <= '9') { goto num_exp_digits; }
298 [ + + + + ]: 96 : if (c == '-' || c == '+') { goto num_exp_first_digit; }
299 [ # # ]: 4 : p--;
300 : 1 : }
301 : 4 : goto done_invalid;
302 : :
303 : 69 : num_exp_first_digit:
304 [ + + ]: 92 : if (spdk_likely(p != buf_end)) {
305 [ # # # # ]: 84 : c = *p++;
306 [ + + + + ]: 84 : if (c >= '0' && c <= '9') { goto num_exp_digits; }
307 [ # # ]: 8 : p--;
308 : 2 : }
309 : 16 : goto done_invalid;
310 : :
311 : 99 : num_exp_digits:
312 [ + + ]: 252 : if (spdk_likely(p != buf_end)) {
313 [ # # # # ]: 132 : c = *p++;
314 [ + + + + ]: 132 : if (c >= '0' && c <= '9') { goto num_exp_digits; }
315 [ # # ]: 12 : p--;
316 : 3 : }
317 : 132 : goto done_valid;
318 : :
319 : 212543 : done_valid:
320 : : /* Valid end state */
321 : 229620 : return p - start;
322 : :
323 : 33 : done_invalid:
324 : : /* Invalid end state */
325 [ + + ]: 44 : if (p == buf_end) {
326 : : /* Hit the end of the buffer - the stream is incomplete. */
327 : 20 : return SPDK_JSON_PARSE_INCOMPLETE;
328 : : }
329 : :
330 : : /* Found an invalid character in an invalid end state */
331 : 24 : return SPDK_JSON_PARSE_INVALID;
332 : 17088 : }
333 : :
334 : : static int
335 : 80 : json_valid_comment(const uint8_t *start, const uint8_t *buf_end)
336 : : {
337 : 80 : const uint8_t *p = start;
338 : : bool multiline;
339 : :
340 [ + + # # ]: 80 : assert(buf_end > p);
341 [ + + ]: 80 : if (buf_end - p < 2) {
342 : 4 : return SPDK_JSON_PARSE_INCOMPLETE;
343 : : }
344 : :
345 [ - + # # : 76 : if (p[0] != '/') {
# # ]
346 : 0 : return SPDK_JSON_PARSE_INVALID;
347 : : }
348 [ + + # # : 76 : if (p[1] == '*') {
# # ]
349 : 36 : multiline = true;
350 [ + + # # : 49 : } else if (p[1] == '/') {
# # ]
351 : 36 : multiline = false;
352 : 9 : } else {
353 : 4 : return SPDK_JSON_PARSE_INVALID;
354 : : }
355 [ # # ]: 72 : p += 2;
356 : :
357 [ + + # # ]: 72 : if (multiline) {
358 [ + - # # ]: 252 : while (p != buf_end - 1) {
359 [ + + + + : 252 : if (p[0] == '*' && p[1] == '/') {
# # # # #
# # # ]
360 : : /* Include the terminating star and slash in the comment */
361 [ # # ]: 36 : return p - start + 2;
362 : : }
363 [ # # ]: 216 : p++;
364 : : }
365 : 0 : } else {
366 [ + + ]: 208 : while (p != buf_end) {
367 [ + + + + : 200 : if (*p == '\r' || *p == '\n') {
# # # # ]
368 : : /* Do not include the line terminator in the comment */
369 : 28 : return p - start;
370 : : }
371 [ # # ]: 172 : p++;
372 : : }
373 : : }
374 : :
375 : 8 : return SPDK_JSON_PARSE_INCOMPLETE;
376 : 20 : }
377 : :
378 : : struct json_literal {
379 : : enum spdk_json_val_type type;
380 : : uint32_t len;
381 : : uint8_t str[8];
382 : : };
383 : :
384 : : /*
385 : : * JSON only defines 3 possible literals; they can be uniquely identified by bits
386 : : * 3 and 4 of the first character:
387 : : * 'f' = 0b11[00]110
388 : : * 'n' = 0b11[01]110
389 : : * 't' = 0b11[10]100
390 : : * These two bits can be used as an index into the g_json_literals array.
391 : : */
392 : : static const struct json_literal g_json_literals[] = {
393 : : {SPDK_JSON_VAL_FALSE, 5, "false"},
394 : : {SPDK_JSON_VAL_NULL, 4, "null"},
395 : : {SPDK_JSON_VAL_TRUE, 4, "true"},
396 : : {}
397 : : };
398 : :
399 : : static int
400 : 91376 : match_literal(const uint8_t *start, const uint8_t *end, const uint8_t *literal, size_t len)
401 : : {
402 [ + + # # ]: 91376 : assert(end >= start);
403 [ + + ]: 91376 : if ((size_t)(end - start) < len) {
404 : 24 : return SPDK_JSON_PARSE_INCOMPLETE;
405 : : }
406 : :
407 [ + + + + : 91352 : if (memcmp(start, literal, len) != 0) {
+ + ]
408 : 12 : return SPDK_JSON_PARSE_INVALID;
409 : : }
410 : :
411 : 91340 : return len;
412 : 4279 : }
413 : :
414 : : ssize_t
415 : 147737 : spdk_json_parse(void *json, size_t size, struct spdk_json_val *values, size_t num_values,
416 : : void **end, uint32_t flags)
417 : : {
418 : 147737 : uint8_t *json_end = json + size;
419 : 48459 : enum spdk_json_val_type containers[SPDK_JSON_MAX_NESTING_DEPTH];
420 : 48459 : size_t con_value[SPDK_JSON_MAX_NESTING_DEPTH];
421 : 147737 : enum spdk_json_val_type con_type = SPDK_JSON_VAL_INVALID;
422 : 147737 : bool trailing_comma = false;
423 : 147737 : size_t depth = 0; /* index into containers */
424 : 147737 : size_t cur_value = 0; /* index into values */
425 : : size_t con_start_value;
426 : 147737 : uint8_t *data = json;
427 : 48459 : uint8_t *new_data;
428 : 147737 : int rc = 0;
429 : : const struct json_literal *lit;
430 : : enum {
431 : : STATE_VALUE, /* initial state */
432 : : STATE_VALUE_SEPARATOR, /* value separator (comma) */
433 : : STATE_NAME, /* "name": value */
434 : : STATE_NAME_SEPARATOR, /* colon */
435 : : STATE_END, /* parsed the complete value, so only whitespace is valid */
436 : 147737 : } state = STATE_VALUE;
437 : :
438 : : #define ADD_VALUE(t, val_start_ptr, val_end_ptr) \
439 : : if (values && cur_value < num_values) { \
440 : : values[cur_value].type = t; \
441 : : values[cur_value].start = val_start_ptr; \
442 : : values[cur_value].len = val_end_ptr - val_start_ptr; \
443 : : } \
444 : : cur_value++
445 : :
446 [ + + ]: 7418849 : while (data < json_end) {
447 [ + - ]: 7374806 : uint8_t c = *data;
448 : :
449 [ + + + + : 7374806 : switch (c) {
+ + + + +
+ ]
450 : 3730735 : case ' ':
451 : : case '\t':
452 : : case '\r':
453 : : case '\n':
454 : : /* Whitespace is allowed between any tokens. */
455 [ + - ]: 4054344 : data++;
456 : 4054344 : break;
457 : :
458 : 87097 : case 't':
459 : : case 'f':
460 : : case 'n':
461 : : /* true, false, or null */
462 [ + + ]: 91376 : if (state != STATE_VALUE) { goto done_invalid; }
463 [ + - + - : 91376 : lit = &g_json_literals[(c >> 3) & 3]; /* See comment above g_json_literals[] */
+ - ]
464 [ + + + - : 91376 : assert(lit->str[0] == c);
+ - + - #
# ]
465 [ + - + - : 91376 : rc = match_literal(data, json_end, lit->str, lit->len);
+ - ]
466 [ + + ]: 91376 : if (rc < 0) { goto done_rc; }
467 [ + + + + : 91340 : ADD_VALUE(lit->type, data, data + rc);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
468 [ + - ]: 91340 : data += rc;
469 [ + + ]: 91340 : state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
470 : 91340 : trailing_comma = false;
471 : 91340 : break;
472 : :
473 : 1089811 : case '"':
474 [ + + + + ]: 1148106 : if (state != STATE_VALUE && state != STATE_NAME) { goto done_invalid; }
475 : 1148106 : rc = json_decode_string(data, json_end, &new_data, flags);
476 [ + + ]: 1148106 : if (rc < 0) {
477 : 596 : data = new_data;
478 : 596 : goto done_rc;
479 : : }
480 : : /*
481 : : * Start is data + 1 to skip initial quote.
482 : : * Length is data + rc - 1 to skip both quotes.
483 : : */
484 [ + + + + : 1147510 : ADD_VALUE(state == STATE_VALUE ? SPDK_JSON_VAL_STRING : SPDK_JSON_VAL_NAME,
+ + + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
485 : : data + 1, data + rc - 1);
486 : 1147510 : data = new_data;
487 [ + + ]: 1147510 : if (state == STATE_NAME) {
488 : 777258 : state = STATE_NAME_SEPARATOR;
489 : 41701 : } else {
490 [ + + ]: 370252 : state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
491 : : }
492 : 1147510 : trailing_comma = false;
493 : 1147510 : break;
494 : :
495 : 212582 : case '-':
496 : : case '0':
497 : : case '1':
498 : : case '2':
499 : : case '3':
500 : : case '4':
501 : : case '5':
502 : : case '6':
503 : : case '7':
504 : : case '8':
505 : : case '9':
506 [ + + ]: 229672 : if (state != STATE_VALUE) { goto done_invalid; }
507 : 229664 : rc = json_valid_number(data, json_end);
508 [ + + ]: 229664 : if (rc < 0) { goto done_rc; }
509 [ + + + + : 229620 : ADD_VALUE(SPDK_JSON_VAL_NUMBER, data, data + rc);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
510 [ + - ]: 229620 : data += rc;
511 [ + + ]: 229620 : state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
512 : 229620 : trailing_comma = false;
513 : 229620 : break;
514 : :
515 : 230189 : case '{':
516 : : case '[':
517 [ + + ]: 242498 : if (state != STATE_VALUE) { goto done_invalid; }
518 [ + + ]: 242498 : if (depth == SPDK_JSON_MAX_NESTING_DEPTH) {
519 : 4 : rc = SPDK_JSON_PARSE_MAX_DEPTH_EXCEEDED;
520 : 4 : goto done_rc;
521 : : }
522 [ + + ]: 242494 : if (c == '{') {
523 : 221736 : con_type = SPDK_JSON_VAL_OBJECT_BEGIN;
524 : 221736 : state = STATE_NAME;
525 : 10873 : } else {
526 : 20758 : con_type = SPDK_JSON_VAL_ARRAY_BEGIN;
527 : 20758 : state = STATE_VALUE;
528 : : }
529 [ + - + - : 242494 : con_value[depth] = cur_value;
+ - ]
530 [ + - + - : 242494 : containers[depth++] = con_type;
+ - ]
531 [ + + + + : 242494 : ADD_VALUE(con_type, data, data + 1);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
532 [ + - ]: 242494 : data++;
533 : 242494 : trailing_comma = false;
534 : 242494 : break;
535 : :
536 : 229544 : case '}':
537 : : case ']':
538 [ + + + - ]: 241638 : if (trailing_comma) { goto done_invalid; }
539 [ + + ]: 241630 : if (depth == 0) { goto done_invalid; }
540 [ + - + - : 241622 : con_type = containers[--depth];
+ - ]
541 [ + - + - : 241622 : con_start_value = con_value[depth];
+ - ]
542 [ + + + + ]: 241622 : if (values && con_start_value < num_values) {
543 [ + - + - : 120783 : values[con_start_value].len = cur_value - con_start_value - 1;
+ - ]
544 : 6038 : }
545 [ + + ]: 241622 : if (c == '}') {
546 [ + + + + ]: 221464 : if (state != STATE_NAME && state != STATE_VALUE_SEPARATOR) {
547 : 8 : goto done_invalid;
548 : : }
549 [ + + ]: 221456 : if (con_type != SPDK_JSON_VAL_OBJECT_BEGIN) {
550 : 8 : goto done_invalid;
551 : : }
552 [ + + + + : 221448 : ADD_VALUE(SPDK_JSON_VAL_OBJECT_END, data, data + 1);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
553 : 10801 : } else {
554 [ + + + + ]: 20158 : if (state != STATE_VALUE && state != STATE_VALUE_SEPARATOR) {
555 : 4 : goto done_invalid;
556 : : }
557 [ + + ]: 20154 : if (con_type != SPDK_JSON_VAL_ARRAY_BEGIN) {
558 : 4 : goto done_invalid;
559 : : }
560 [ + + + + : 20150 : ADD_VALUE(SPDK_JSON_VAL_ARRAY_END, data, data + 1);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
561 : : }
562 [ + + + - : 241598 : con_type = depth == 0 ? SPDK_JSON_VAL_INVALID : containers[depth - 1];
+ - + - ]
563 [ + - ]: 241598 : data++;
564 [ + + ]: 241598 : state = depth ? STATE_VALUE_SEPARATOR : STATE_END;
565 : 241598 : trailing_comma = false;
566 : 241598 : break;
567 : :
568 : 555715 : case ',':
569 [ + + ]: 589814 : if (state != STATE_VALUE_SEPARATOR) { goto done_invalid; }
570 [ + - ]: 589790 : data++;
571 [ + + + + : 589790 : assert(con_type == SPDK_JSON_VAL_ARRAY_BEGIN ||
# # ]
572 : : con_type == SPDK_JSON_VAL_OBJECT_BEGIN);
573 [ + + ]: 589790 : state = con_type == SPDK_JSON_VAL_ARRAY_BEGIN ? STATE_VALUE : STATE_NAME;
574 : 589790 : trailing_comma = true;
575 : 589790 : break;
576 : :
577 : 735530 : case ':':
578 [ + + ]: 777222 : if (state != STATE_NAME_SEPARATOR) { goto done_invalid; }
579 [ + - ]: 777222 : data++;
580 : 777222 : state = STATE_VALUE;
581 : 777222 : break;
582 : :
583 : 69 : case '/':
584 [ + + ]: 92 : if (!(flags & SPDK_JSON_PARSE_FLAG_ALLOW_COMMENTS)) {
585 : 12 : goto done_invalid;
586 : : }
587 : 80 : rc = json_valid_comment(data, json_end);
588 [ + + ]: 80 : if (rc < 0) { goto done_rc; }
589 : : /* Skip over comment */
590 [ # # ]: 64 : data += rc;
591 : 64 : break;
592 : :
593 : 33 : default:
594 : 44 : goto done_invalid;
595 : : }
596 : :
597 [ + + ]: 7373982 : if (state == STATE_END) {
598 : 102870 : break;
599 : : }
600 : : }
601 : :
602 [ + + ]: 146913 : if (state == STATE_END) {
603 : : /* Skip trailing whitespace */
604 [ + + ]: 137610 : while (data < json_end) {
605 [ + - ]: 34980 : uint8_t c = *data;
606 : :
607 [ + + + - : 34980 : if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ - + + ]
608 [ + - ]: 34740 : data++;
609 : 2616 : } else {
610 : 52 : break;
611 : : }
612 : : }
613 : :
614 : : /*
615 : : * These asserts are just for sanity checking - they are guaranteed by the allowed
616 : : * state transitions.
617 : : */
618 [ + + # # ]: 102870 : assert(depth == 0);
619 [ + + + - : 102870 : assert(trailing_comma == false);
# # ]
620 [ + + # # ]: 102870 : assert(data <= json_end);
621 [ + + ]: 102870 : if (end) {
622 [ + - ]: 102836 : *end = data;
623 : 3770 : }
624 : 102870 : return cur_value;
625 : : }
626 : :
627 : : /* Invalid end state - ran out of data */
628 : 44043 : rc = SPDK_JSON_PARSE_INCOMPLETE;
629 : :
630 : 43594 : done_rc:
631 [ + + # # ]: 44867 : assert(rc < 0);
632 [ + - ]: 44867 : if (end) {
633 [ + - ]: 44867 : *end = data;
634 : 1273 : }
635 : 44867 : return rc;
636 : :
637 : 96 : done_invalid:
638 : 128 : rc = SPDK_JSON_PARSE_INVALID;
639 : 128 : goto done_rc;
640 : 5050 : }
|