xref: /vim-8.2.3635/src/json.c (revision 2950065e)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * json.c: Encoding and decoding JSON.
12  *
13  * Follows this standard: https://tools.ietf.org/html/rfc7159.html
14  */
15 #define USING_FLOAT_STUFF
16 
17 #include "vim.h"
18 
19 #if defined(FEAT_EVAL) || defined(PROTO)
20 
21 static int json_encode_item(garray_T *gap, typval_T *val, int copyID, int options);
22 
23 static char e_json_error[] = N_("E491: json decode error at '%s'");
24 
25 /*
26  * Encode "val" into a JSON format string.
27  * The result is added to "gap"
28  * Returns FAIL on failure and makes gap->ga_data empty.
29  */
30     static int
json_encode_gap(garray_T * gap,typval_T * val,int options)31 json_encode_gap(garray_T *gap, typval_T *val, int options)
32 {
33     if (json_encode_item(gap, val, get_copyID(), options) == FAIL)
34     {
35 	ga_clear(gap);
36 	gap->ga_data = vim_strsave((char_u *)"");
37 	return FAIL;
38     }
39     return OK;
40 }
41 
42 /*
43  * Encode "val" into a JSON format string.
44  * The result is in allocated memory.
45  * The result is empty when encoding fails.
46  * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL.
47  */
48     char_u *
json_encode(typval_T * val,int options)49 json_encode(typval_T *val, int options)
50 {
51     garray_T ga;
52 
53     // Store bytes in the growarray.
54     ga_init2(&ga, 1, 4000);
55     json_encode_gap(&ga, val, options);
56     ga_append(&ga, NUL);
57     return ga.ga_data;
58 }
59 
60 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
61 /*
62  * Encode ["nr", "val"] into a JSON format string in allocated memory.
63  * "options" can contain JSON_JS, JSON_NO_NONE and JSON_NL.
64  * Returns NULL when out of memory.
65  */
66     char_u *
json_encode_nr_expr(int nr,typval_T * val,int options)67 json_encode_nr_expr(int nr, typval_T *val, int options)
68 {
69     typval_T	listtv;
70     typval_T	nrtv;
71     garray_T	ga;
72 
73     nrtv.v_type = VAR_NUMBER;
74     nrtv.vval.v_number = nr;
75     if (rettv_list_alloc(&listtv) == FAIL)
76 	return NULL;
77     if (list_append_tv(listtv.vval.v_list, &nrtv) == FAIL
78 	    || list_append_tv(listtv.vval.v_list, val) == FAIL)
79     {
80 	list_unref(listtv.vval.v_list);
81 	return NULL;
82     }
83 
84     ga_init2(&ga, 1, 4000);
85     if (json_encode_gap(&ga, &listtv, options) == OK && (options & JSON_NL))
86 	ga_append(&ga, '\n');
87     list_unref(listtv.vval.v_list);
88     ga_append(&ga, NUL);
89     return ga.ga_data;
90 }
91 #endif
92 
93     static void
write_string(garray_T * gap,char_u * str)94 write_string(garray_T *gap, char_u *str)
95 {
96     char_u	*res = str;
97     char_u	numbuf[NUMBUFLEN];
98 
99     if (res == NULL)
100 	ga_concat(gap, (char_u *)"\"\"");
101     else
102     {
103 #if defined(USE_ICONV)
104 	vimconv_T   conv;
105 	char_u	    *converted = NULL;
106 
107 	if (!enc_utf8)
108 	{
109 	    // Convert the text from 'encoding' to utf-8, the JSON string is
110 	    // always utf-8.
111 	    conv.vc_type = CONV_NONE;
112 	    convert_setup(&conv, p_enc, (char_u*)"utf-8");
113 	    if (conv.vc_type != CONV_NONE)
114 		converted = res = string_convert(&conv, res, NULL);
115 	    convert_setup(&conv, NULL, NULL);
116 	}
117 #endif
118 	ga_append(gap, '"');
119 	while (*res != NUL)
120 	{
121 	    int c;
122 	    // always use utf-8 encoding, ignore 'encoding'
123 	    c = utf_ptr2char(res);
124 
125 	    switch (c)
126 	    {
127 		case 0x08:
128 		    ga_append(gap, '\\'); ga_append(gap, 'b'); break;
129 		case 0x09:
130 		    ga_append(gap, '\\'); ga_append(gap, 't'); break;
131 		case 0x0a:
132 		    ga_append(gap, '\\'); ga_append(gap, 'n'); break;
133 		case 0x0c:
134 		    ga_append(gap, '\\'); ga_append(gap, 'f'); break;
135 		case 0x0d:
136 		    ga_append(gap, '\\'); ga_append(gap, 'r'); break;
137 		case 0x22: // "
138 		case 0x5c: // backslash
139 		    ga_append(gap, '\\');
140 		    ga_append(gap, c);
141 		    break;
142 		default:
143 		    if (c >= 0x20)
144 		    {
145 			numbuf[utf_char2bytes(c, numbuf)] = NUL;
146 			ga_concat(gap, numbuf);
147 		    }
148 		    else
149 		    {
150 			vim_snprintf((char *)numbuf, NUMBUFLEN,
151 							 "\\u%04lx", (long)c);
152 			ga_concat(gap, numbuf);
153 		    }
154 	    }
155 	    res += utf_ptr2len(res);
156 	}
157 	ga_append(gap, '"');
158 #if defined(USE_ICONV)
159 	vim_free(converted);
160 #endif
161     }
162 }
163 
164 /*
165  * Return TRUE if "key" can be used without quotes.
166  * That is when it starts with a letter and only contains letters, digits and
167  * underscore.
168  */
169     static int
is_simple_key(char_u * key)170 is_simple_key(char_u *key)
171 {
172     char_u *p;
173 
174     if (!ASCII_ISALPHA(*key))
175 	return FALSE;
176     for (p = key + 1; *p != NUL; ++p)
177 	if (!ASCII_ISALPHA(*p) && *p != '_' && !vim_isdigit(*p))
178 	    return FALSE;
179     return TRUE;
180 }
181 
182 /*
183  * Encode "val" into "gap".
184  * Return FAIL or OK.
185  */
186     static int
json_encode_item(garray_T * gap,typval_T * val,int copyID,int options)187 json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
188 {
189     char_u	numbuf[NUMBUFLEN];
190     char_u	*res;
191     blob_T	*b;
192     list_T	*l;
193     dict_T	*d;
194     int		i;
195 
196     switch (val->v_type)
197     {
198 	case VAR_BOOL:
199 	    switch ((long)val->vval.v_number)
200 	    {
201 		case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break;
202 		case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break;
203 	    }
204 	    break;
205 
206 	case VAR_SPECIAL:
207 	    switch ((long)val->vval.v_number)
208 	    {
209 		case VVAL_NONE: if ((options & JSON_JS) != 0
210 					     && (options & JSON_NO_NONE) == 0)
211 				    // empty item
212 				    break;
213 				// FALLTHROUGH
214 		case VVAL_NULL: ga_concat(gap, (char_u *)"null"); break;
215 	    }
216 	    break;
217 
218 	case VAR_NUMBER:
219 	    vim_snprintf((char *)numbuf, NUMBUFLEN, "%lld",
220 					      (varnumber_T)val->vval.v_number);
221 	    ga_concat(gap, numbuf);
222 	    break;
223 
224 	case VAR_STRING:
225 	    res = val->vval.v_string;
226 	    write_string(gap, res);
227 	    break;
228 
229 	case VAR_FUNC:
230 	case VAR_PARTIAL:
231 	case VAR_JOB:
232 	case VAR_CHANNEL:
233 	case VAR_INSTR:
234 	    semsg(_(e_cannot_json_encode_str), vartype_name(val->v_type));
235 	    return FAIL;
236 
237 	case VAR_BLOB:
238 	    b = val->vval.v_blob;
239 	    if (b == NULL || b->bv_ga.ga_len == 0)
240 		ga_concat(gap, (char_u *)"[]");
241 	    else
242 	    {
243 		ga_append(gap, '[');
244 		for (i = 0; i < b->bv_ga.ga_len; i++)
245 		{
246 		    if (i > 0)
247 			ga_concat(gap, (char_u *)",");
248 		    vim_snprintf((char *)numbuf, NUMBUFLEN, "%d",
249 			    (int)blob_get(b, i));
250 		    ga_concat(gap, numbuf);
251 		}
252 		ga_append(gap, ']');
253 	    }
254 	    break;
255 
256 	case VAR_LIST:
257 	    l = val->vval.v_list;
258 	    if (l == NULL)
259 		ga_concat(gap, (char_u *)"[]");
260 	    else
261 	    {
262 		if (l->lv_copyID == copyID)
263 		    ga_concat(gap, (char_u *)"[]");
264 		else
265 		{
266 		    listitem_T	*li;
267 
268 		    l->lv_copyID = copyID;
269 		    ga_append(gap, '[');
270 		    CHECK_LIST_MATERIALIZE(l);
271 		    for (li = l->lv_first; li != NULL && !got_int; )
272 		    {
273 			if (json_encode_item(gap, &li->li_tv, copyID,
274 						   options & JSON_JS) == FAIL)
275 			    return FAIL;
276 			if ((options & JSON_JS)
277 				&& li->li_next == NULL
278 				&& li->li_tv.v_type == VAR_SPECIAL
279 				&& li->li_tv.vval.v_number == VVAL_NONE)
280 			    // add an extra comma if the last item is v:none
281 			    ga_append(gap, ',');
282 			li = li->li_next;
283 			if (li != NULL)
284 			    ga_append(gap, ',');
285 		    }
286 		    ga_append(gap, ']');
287 		    l->lv_copyID = 0;
288 		}
289 	    }
290 	    break;
291 
292 	case VAR_DICT:
293 	    d = val->vval.v_dict;
294 	    if (d == NULL)
295 		ga_concat(gap, (char_u *)"{}");
296 	    else
297 	    {
298 		if (d->dv_copyID == copyID)
299 		    ga_concat(gap, (char_u *)"{}");
300 		else
301 		{
302 		    int		first = TRUE;
303 		    int		todo = (int)d->dv_hashtab.ht_used;
304 		    hashitem_T	*hi;
305 
306 		    d->dv_copyID = copyID;
307 		    ga_append(gap, '{');
308 
309 		    for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int;
310 									 ++hi)
311 			if (!HASHITEM_EMPTY(hi))
312 			{
313 			    --todo;
314 			    if (first)
315 				first = FALSE;
316 			    else
317 				ga_append(gap, ',');
318 			    if ((options & JSON_JS)
319 						 && is_simple_key(hi->hi_key))
320 				ga_concat(gap, hi->hi_key);
321 			    else
322 				write_string(gap, hi->hi_key);
323 			    ga_append(gap, ':');
324 			    if (json_encode_item(gap, &dict_lookup(hi)->di_tv,
325 				      copyID, options | JSON_NO_NONE) == FAIL)
326 				return FAIL;
327 			}
328 		    ga_append(gap, '}');
329 		    d->dv_copyID = 0;
330 		}
331 	    }
332 	    break;
333 
334 	case VAR_FLOAT:
335 #ifdef FEAT_FLOAT
336 # if defined(HAVE_MATH_H)
337 	    if (isnan(val->vval.v_float))
338 		ga_concat(gap, (char_u *)"NaN");
339 	    else if (isinf(val->vval.v_float))
340 	    {
341 		if (val->vval.v_float < 0.0)
342 		    ga_concat(gap, (char_u *)"-Infinity");
343 		else
344 		    ga_concat(gap, (char_u *)"Infinity");
345 	    }
346 	    else
347 # endif
348 	    {
349 		vim_snprintf((char *)numbuf, NUMBUFLEN, "%g",
350 							   val->vval.v_float);
351 		ga_concat(gap, numbuf);
352 	    }
353 	    break;
354 #endif
355 	case VAR_UNKNOWN:
356 	case VAR_ANY:
357 	case VAR_VOID:
358 	    internal_error_no_abort("json_encode_item()");
359 	    return FAIL;
360     }
361     return OK;
362 }
363 
364 /*
365  * When "reader" has less than NUMBUFLEN bytes available, call the fill
366  * callback to get more.
367  */
368     static void
fill_numbuflen(js_read_T * reader)369 fill_numbuflen(js_read_T *reader)
370 {
371     if (reader->js_fill != NULL && (int)(reader->js_end - reader->js_buf)
372 						- reader->js_used < NUMBUFLEN)
373     {
374 	if (reader->js_fill(reader))
375 	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
376     }
377 }
378 
379 /*
380  * Skip white space in "reader".  All characters <= space are considered white
381  * space.
382  * Also tops up readahead when needed.
383  */
384     static void
json_skip_white(js_read_T * reader)385 json_skip_white(js_read_T *reader)
386 {
387     int c;
388 
389     for (;;)
390     {
391 	c = reader->js_buf[reader->js_used];
392 	if (reader->js_fill != NULL && c == NUL)
393 	{
394 	    if (reader->js_fill(reader))
395 	    {
396 		reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
397 		continue;
398 	    }
399 	}
400 	if (c == NUL || c > ' ')
401 	    break;
402 	++reader->js_used;
403     }
404     fill_numbuflen(reader);
405 }
406 
407     static int
json_decode_string(js_read_T * reader,typval_T * res,int quote)408 json_decode_string(js_read_T *reader, typval_T *res, int quote)
409 {
410     garray_T    ga;
411     int		len;
412     char_u	*p;
413     int		c;
414     varnumber_T	nr;
415 
416     if (res != NULL)
417 	ga_init2(&ga, 1, 200);
418 
419     p = reader->js_buf + reader->js_used + 1; // skip over " or '
420     while (*p != quote)
421     {
422 	// The JSON is always expected to be utf-8, thus use utf functions
423 	// here. The string is converted below if needed.
424 	if (*p == NUL || p[1] == NUL || utf_ptr2len(p) < utf_byte2len(*p))
425 	{
426 	    // Not enough bytes to make a character or end of the string. Get
427 	    // more if possible.
428 	    if (reader->js_fill == NULL)
429 		break;
430 	    len = (int)(reader->js_end - p);
431 	    reader->js_used = (int)(p - reader->js_buf);
432 	    if (!reader->js_fill(reader))
433 		break; // didn't get more
434 	    p = reader->js_buf + reader->js_used;
435 	    reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
436 	    continue;
437 	}
438 
439 	if (*p == '\\')
440 	{
441 	    c = -1;
442 	    switch (p[1])
443 	    {
444 		case '\\': c = '\\'; break;
445 		case '"': c = '"'; break;
446 		case 'b': c = BS; break;
447 		case 't': c = TAB; break;
448 		case 'n': c = NL; break;
449 		case 'f': c = FF; break;
450 		case 'r': c = CAR; break;
451 		case 'u':
452 		    if (reader->js_fill != NULL
453 				     && (int)(reader->js_end - p) < NUMBUFLEN)
454 		    {
455 			reader->js_used = (int)(p - reader->js_buf);
456 			if (reader->js_fill(reader))
457 			{
458 			    p = reader->js_buf + reader->js_used;
459 			    reader->js_end = reader->js_buf
460 						     + STRLEN(reader->js_buf);
461 			}
462 		    }
463 		    nr = 0;
464 		    len = 0;
465 		    vim_str2nr(p + 2, NULL, &len,
466 			     STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE);
467 		    if (len == 0)
468 		    {
469 			if (res != NULL)
470 			    ga_clear(&ga);
471 			return FAIL;
472 		    }
473 		    p += len + 2;
474 		    if (0xd800 <= nr && nr <= 0xdfff
475 			    && (int)(reader->js_end - p) >= 6
476 			    && *p == '\\' && *(p+1) == 'u')
477 		    {
478 			varnumber_T	nr2 = 0;
479 
480 			// decode surrogate pair: \ud812\u3456
481 			len = 0;
482 			vim_str2nr(p + 2, NULL, &len,
483 			     STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE);
484 			if (len == 0)
485 			{
486 			    if (res != NULL)
487 				ga_clear(&ga);
488 			    return FAIL;
489 			}
490 			if (0xdc00 <= nr2 && nr2 <= 0xdfff)
491 			{
492 			    p += len + 2;
493 			    nr = (((nr - 0xd800) << 10) |
494 				((nr2 - 0xdc00) & 0x3ff)) + 0x10000;
495 			}
496 		    }
497 		    if (res != NULL)
498 		    {
499 			char_u	buf[NUMBUFLEN];
500 
501 			buf[utf_char2bytes((int)nr, buf)] = NUL;
502 			ga_concat(&ga, buf);
503 		    }
504 		    break;
505 		default:
506 		    // not a special char, skip over backslash
507 		    ++p;
508 		    continue;
509 	    }
510 	    if (c > 0)
511 	    {
512 		p += 2;
513 		if (res != NULL)
514 		    ga_append(&ga, c);
515 	    }
516 	}
517 	else
518 	{
519 	    len = utf_ptr2len(p);
520 	    if (res != NULL)
521 	    {
522 		if (ga_grow(&ga, len) == FAIL)
523 		{
524 		    ga_clear(&ga);
525 		    return FAIL;
526 		}
527 		mch_memmove((char *)ga.ga_data + ga.ga_len, p, (size_t)len);
528 		ga.ga_len += len;
529 	    }
530 	    p += len;
531 	}
532     }
533 
534     reader->js_used = (int)(p - reader->js_buf);
535     if (*p == quote)
536     {
537 	++reader->js_used;
538 	if (res != NULL)
539 	{
540 	    ga_append(&ga, NUL);
541 	    res->v_type = VAR_STRING;
542 #if defined(USE_ICONV)
543 	    if (!enc_utf8)
544 	    {
545 		vimconv_T   conv;
546 
547 		// Convert the utf-8 string to 'encoding'.
548 		conv.vc_type = CONV_NONE;
549 		convert_setup(&conv, (char_u*)"utf-8", p_enc);
550 		if (conv.vc_type != CONV_NONE)
551 		{
552 		    res->vval.v_string =
553 				      string_convert(&conv, ga.ga_data, NULL);
554 		    vim_free(ga.ga_data);
555 		}
556 		convert_setup(&conv, NULL, NULL);
557 	    }
558 	    else
559 #endif
560 		res->vval.v_string = ga.ga_data;
561 	}
562 	return OK;
563     }
564     if (res != NULL)
565     {
566 	res->v_type = VAR_SPECIAL;
567 	res->vval.v_number = VVAL_NONE;
568 	ga_clear(&ga);
569     }
570     return MAYBE;
571 }
572 
573 typedef enum {
574     JSON_ARRAY,		// parsing items in an array
575     JSON_OBJECT_KEY,	// parsing key of an object
576     JSON_OBJECT		// parsing item in an object, after the key
577 } json_decode_T;
578 
579 typedef struct {
580     json_decode_T jd_type;
581     typval_T	  jd_tv;	// the list or dict
582     typval_T	  jd_key_tv;
583     char_u	  *jd_key;
584 } json_dec_item_T;
585 
586 /*
587  * Decode one item and put it in "res".  If "res" is NULL only advance.
588  * Must already have skipped white space.
589  *
590  * Return FAIL for a decoding error (and give an error).
591  * Return MAYBE for an incomplete message.
592  */
593     static int
json_decode_item(js_read_T * reader,typval_T * res,int options)594 json_decode_item(js_read_T *reader, typval_T *res, int options)
595 {
596     char_u	*p;
597     int		i;
598     int		len;
599     int		retval;
600     garray_T	stack;
601     typval_T	item;
602     typval_T	*cur_item;
603     json_dec_item_T *top_item;
604     char_u	key_buf[NUMBUFLEN];
605 
606     ga_init2(&stack, sizeof(json_dec_item_T), 100);
607     cur_item = res;
608     init_tv(&item);
609     if (res != NULL)
610 	init_tv(res);
611 
612     fill_numbuflen(reader);
613     p = reader->js_buf + reader->js_used;
614     for (;;)
615     {
616 	top_item = NULL;
617 	if (stack.ga_len > 0)
618 	{
619 	    top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
620 	    json_skip_white(reader);
621 	    p = reader->js_buf + reader->js_used;
622 	    if (*p == NUL)
623 	    {
624 		retval = MAYBE;
625 		goto theend;
626 	    }
627 	    if (top_item->jd_type == JSON_OBJECT_KEY
628 					    || top_item->jd_type == JSON_ARRAY)
629 	    {
630 		// Check for end of object or array.
631 		if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}'))
632 		{
633 		    ++reader->js_used; // consume the ']' or '}'
634 		    --stack.ga_len;
635 		    if (stack.ga_len == 0)
636 		    {
637 			retval = OK;
638 			goto theend;
639 		    }
640 		    if (cur_item != NULL)
641 			cur_item = &top_item->jd_tv;
642 		    goto item_end;
643 		}
644 	    }
645 	}
646 
647 	if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
648 		&& (options & JSON_JS)
649 		&& reader->js_buf[reader->js_used] != '"'
650 		&& reader->js_buf[reader->js_used] != '\''
651 		&& reader->js_buf[reader->js_used] != '['
652 		&& reader->js_buf[reader->js_used] != '{')
653 	{
654 	    char_u *key;
655 
656 	    // accept an object key that is not in quotes
657 	    key = p = reader->js_buf + reader->js_used;
658 	    while (*p != NUL && *p != ':' && *p > ' ')
659 		++p;
660 	    if (cur_item != NULL)
661 	    {
662 		cur_item->v_type = VAR_STRING;
663 		cur_item->vval.v_string = vim_strnsave(key, p - key);
664 		top_item->jd_key = cur_item->vval.v_string;
665 	    }
666 	    reader->js_used += (int)(p - key);
667 	}
668 	else
669 	{
670 	    switch (*p)
671 	    {
672 		case '[': // start of array
673 		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
674 		    {
675 			retval = FAIL;
676 			break;
677 		    }
678 		    if (ga_grow(&stack, 1) == FAIL)
679 		    {
680 			retval = FAIL;
681 			break;
682 		    }
683 		    if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL)
684 		    {
685 			cur_item->v_type = VAR_SPECIAL;
686 			cur_item->vval.v_number = VVAL_NONE;
687 			retval = FAIL;
688 			break;
689 		    }
690 
691 		    ++reader->js_used; // consume the '['
692 		    top_item = ((json_dec_item_T *)stack.ga_data)
693 								+ stack.ga_len;
694 		    top_item->jd_type = JSON_ARRAY;
695 		    ++stack.ga_len;
696 		    if (cur_item != NULL)
697 		    {
698 			top_item->jd_tv = *cur_item;
699 			cur_item = &item;
700 		    }
701 		    continue;
702 
703 		case '{': // start of object
704 		    if (top_item && top_item->jd_type == JSON_OBJECT_KEY)
705 		    {
706 			retval = FAIL;
707 			break;
708 		    }
709 		    if (ga_grow(&stack, 1) == FAIL)
710 		    {
711 			retval = FAIL;
712 			break;
713 		    }
714 		    if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL)
715 		    {
716 			cur_item->v_type = VAR_SPECIAL;
717 			cur_item->vval.v_number = VVAL_NONE;
718 			retval = FAIL;
719 			break;
720 		    }
721 
722 		    ++reader->js_used; // consume the '{'
723 		    top_item = ((json_dec_item_T *)stack.ga_data)
724 								+ stack.ga_len;
725 		    top_item->jd_type = JSON_OBJECT_KEY;
726 		    ++stack.ga_len;
727 		    if (cur_item != NULL)
728 		    {
729 			top_item->jd_tv = *cur_item;
730 			cur_item = &top_item->jd_key_tv;
731 		    }
732 		    continue;
733 
734 		case '"': // string
735 		    retval = json_decode_string(reader, cur_item, *p);
736 		    break;
737 
738 		case '\'':
739 		    if (options & JSON_JS)
740 			retval = json_decode_string(reader, cur_item, *p);
741 		    else
742 		    {
743 			semsg(_(e_json_error), p);
744 			retval = FAIL;
745 		    }
746 		    break;
747 
748 		case ',': // comma: empty item
749 		    if ((options & JSON_JS) == 0)
750 		    {
751 			semsg(_(e_json_error), p);
752 			retval = FAIL;
753 			break;
754 		    }
755 		    // FALLTHROUGH
756 		case NUL: // empty
757 		    if (cur_item != NULL)
758 		    {
759 			cur_item->v_type = VAR_SPECIAL;
760 			cur_item->vval.v_number = VVAL_NONE;
761 		    }
762 		    retval = OK;
763 		    break;
764 
765 		default:
766 		    if (VIM_ISDIGIT(*p) || (*p == '-'
767 					&& (VIM_ISDIGIT(p[1]) || p[1] == NUL)))
768 		    {
769 			char_u  *sp = p;
770 
771 			if (*sp == '-')
772 			{
773 			    ++sp;
774 			    if (*sp == NUL)
775 			    {
776 				retval = MAYBE;
777 				break;
778 			    }
779 			    if (!VIM_ISDIGIT(*sp))
780 			    {
781 				semsg(_(e_json_error), p);
782 				retval = FAIL;
783 				break;
784 			    }
785 			}
786 			sp = skipdigits(sp);
787 #ifdef FEAT_FLOAT
788 			if (*sp == '.' || *sp == 'e' || *sp == 'E')
789 			{
790 			    if (cur_item == NULL)
791 			    {
792 				float_T f;
793 
794 				len = string2float(p, &f, FALSE);
795 			    }
796 			    else
797 			    {
798 				cur_item->v_type = VAR_FLOAT;
799 				len = string2float(p, &cur_item->vval.v_float,
800 									FALSE);
801 			    }
802 			}
803 			else
804 #endif
805 			{
806 			    varnumber_T nr;
807 
808 			    vim_str2nr(reader->js_buf + reader->js_used,
809 				    NULL, &len, 0, // what
810 				    &nr, NULL, 0, TRUE);
811 			    if (len == 0)
812 			    {
813 				semsg(_(e_json_error), p);
814 				retval = FAIL;
815 				goto theend;
816 			    }
817 			    if (cur_item != NULL)
818 			    {
819 				cur_item->v_type = VAR_NUMBER;
820 				cur_item->vval.v_number = nr;
821 			    }
822 			}
823 			reader->js_used += len;
824 			retval = OK;
825 			break;
826 		    }
827 		    if (STRNICMP((char *)p, "false", 5) == 0)
828 		    {
829 			reader->js_used += 5;
830 			if (cur_item != NULL)
831 			{
832 			    cur_item->v_type = VAR_BOOL;
833 			    cur_item->vval.v_number = VVAL_FALSE;
834 			}
835 			retval = OK;
836 			break;
837 		    }
838 		    if (STRNICMP((char *)p, "true", 4) == 0)
839 		    {
840 			reader->js_used += 4;
841 			if (cur_item != NULL)
842 			{
843 			    cur_item->v_type = VAR_BOOL;
844 			    cur_item->vval.v_number = VVAL_TRUE;
845 			}
846 			retval = OK;
847 			break;
848 		    }
849 		    if (STRNICMP((char *)p, "null", 4) == 0)
850 		    {
851 			reader->js_used += 4;
852 			if (cur_item != NULL)
853 			{
854 			    cur_item->v_type = VAR_SPECIAL;
855 			    cur_item->vval.v_number = VVAL_NULL;
856 			}
857 			retval = OK;
858 			break;
859 		    }
860 #ifdef FEAT_FLOAT
861 		    if (STRNICMP((char *)p, "NaN", 3) == 0)
862 		    {
863 			reader->js_used += 3;
864 			if (cur_item != NULL)
865 			{
866 			    cur_item->v_type = VAR_FLOAT;
867 			    cur_item->vval.v_float = NAN;
868 			}
869 			retval = OK;
870 			break;
871 		    }
872 		    if (STRNICMP((char *)p, "-Infinity", 9) == 0)
873 		    {
874 			reader->js_used += 9;
875 			if (cur_item != NULL)
876 			{
877 			    cur_item->v_type = VAR_FLOAT;
878 			    cur_item->vval.v_float = -INFINITY;
879 			}
880 			retval = OK;
881 			break;
882 		    }
883 		    if (STRNICMP((char *)p, "Infinity", 8) == 0)
884 		    {
885 			reader->js_used += 8;
886 			if (cur_item != NULL)
887 			{
888 			    cur_item->v_type = VAR_FLOAT;
889 			    cur_item->vval.v_float = INFINITY;
890 			}
891 			retval = OK;
892 			break;
893 		    }
894 #endif
895 		    // check for truncated name
896 		    len = (int)(reader->js_end
897 					 - (reader->js_buf + reader->js_used));
898 		    if (
899 			    (len < 5 && STRNICMP((char *)p, "false", len) == 0)
900 #ifdef FEAT_FLOAT
901 			    || (len < 9 && STRNICMP((char *)p, "-Infinity", len) == 0)
902 			    || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0)
903 			    || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0)
904 #endif
905 			    || (len < 4 && (STRNICMP((char *)p, "true", len) == 0
906 				       ||  STRNICMP((char *)p, "null", len) == 0)))
907 
908 			retval = MAYBE;
909 		    else
910 			retval = FAIL;
911 		    break;
912 	    }
913 
914 	    // We are finished when retval is FAIL or MAYBE and when at the
915 	    // toplevel.
916 	    if (retval == FAIL)
917 		break;
918 	    if (retval == MAYBE || stack.ga_len == 0)
919 		goto theend;
920 
921 	    if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY
922 		    && cur_item != NULL)
923 	    {
924 #ifdef FEAT_FLOAT
925 		if (cur_item->v_type == VAR_FLOAT)
926 		{
927 		    // cannot use a float as a key
928 		    emsg(_(e_float_as_string));
929 		    retval = FAIL;
930 		    goto theend;
931 		}
932 #endif
933 		top_item->jd_key = tv_get_string_buf_chk(cur_item, key_buf);
934 		if (top_item->jd_key == NULL)
935 		{
936 		    emsg(_(e_invarg));
937 		    retval = FAIL;
938 		    goto theend;
939 		}
940 	    }
941 	}
942 
943 item_end:
944 	top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1;
945 	switch (top_item->jd_type)
946 	{
947 	    case JSON_ARRAY:
948 		if (res != NULL)
949 		{
950 		    listitem_T	*li = listitem_alloc();
951 
952 		    if (li == NULL)
953 		    {
954 			clear_tv(cur_item);
955 			retval = FAIL;
956 			goto theend;
957 		    }
958 		    li->li_tv = *cur_item;
959 		    list_append(top_item->jd_tv.vval.v_list, li);
960 		}
961 		if (cur_item != NULL)
962 		    cur_item = &item;
963 
964 		json_skip_white(reader);
965 		p = reader->js_buf + reader->js_used;
966 		if (*p == ',')
967 		    ++reader->js_used;
968 		else if (*p != ']')
969 		{
970 		    if (*p == NUL)
971 			retval = MAYBE;
972 		    else
973 		    {
974 			semsg(_(e_json_error), p);
975 			retval = FAIL;
976 		    }
977 		    goto theend;
978 		}
979 		break;
980 
981 	    case JSON_OBJECT_KEY:
982 		json_skip_white(reader);
983 		p = reader->js_buf + reader->js_used;
984 		if (*p != ':')
985 		{
986 		    if (cur_item != NULL)
987 			clear_tv(cur_item);
988 		    if (*p == NUL)
989 			retval = MAYBE;
990 		    else
991 		    {
992 			semsg(_(e_json_error), p);
993 			retval = FAIL;
994 		    }
995 		    goto theend;
996 		}
997 		++reader->js_used;
998 		json_skip_white(reader);
999 		top_item->jd_type = JSON_OBJECT;
1000 		if (cur_item != NULL)
1001 		    cur_item = &item;
1002 		break;
1003 
1004 	    case JSON_OBJECT:
1005 		if (cur_item != NULL
1006 			&& dict_find(top_item->jd_tv.vval.v_dict,
1007 						 top_item->jd_key, -1) != NULL)
1008 		{
1009 		    semsg(_("E938: Duplicate key in JSON: \"%s\""),
1010 							     top_item->jd_key);
1011 		    clear_tv(cur_item);
1012 		    retval = FAIL;
1013 		    goto theend;
1014 		}
1015 
1016 		if (cur_item != NULL)
1017 		{
1018 		    dictitem_T *di = dictitem_alloc(top_item->jd_key);
1019 
1020 		    clear_tv(&top_item->jd_key_tv);
1021 		    if (di == NULL)
1022 		    {
1023 			clear_tv(cur_item);
1024 			retval = FAIL;
1025 			goto theend;
1026 		    }
1027 		    di->di_tv = *cur_item;
1028 		    di->di_tv.v_lock = 0;
1029 		    if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL)
1030 		    {
1031 			dictitem_free(di);
1032 			retval = FAIL;
1033 			goto theend;
1034 		    }
1035 		}
1036 
1037 		json_skip_white(reader);
1038 		p = reader->js_buf + reader->js_used;
1039 		if (*p == ',')
1040 		    ++reader->js_used;
1041 		else if (*p != '}')
1042 		{
1043 		    if (*p == NUL)
1044 			retval = MAYBE;
1045 		    else
1046 		    {
1047 			semsg(_(e_json_error), p);
1048 			retval = FAIL;
1049 		    }
1050 		    goto theend;
1051 		}
1052 		top_item->jd_type = JSON_OBJECT_KEY;
1053 		if (cur_item != NULL)
1054 		    cur_item = &top_item->jd_key_tv;
1055 		break;
1056 	}
1057     }
1058 
1059     // Get here when parsing failed.
1060     if (res != NULL)
1061     {
1062 	clear_tv(res);
1063 	res->v_type = VAR_SPECIAL;
1064 	res->vval.v_number = VVAL_NONE;
1065     }
1066     semsg(_(e_json_error), p);
1067 
1068 theend:
1069     for (i = 0; i < stack.ga_len; i++)
1070 	clear_tv(&(((json_dec_item_T *)stack.ga_data) + i)->jd_key_tv);
1071     ga_clear(&stack);
1072 
1073     return retval;
1074 }
1075 
1076 /*
1077  * Decode the JSON from "reader" and store the result in "res".
1078  * "options" can be JSON_JS or zero;
1079  * Return FAIL if not the whole message was consumed.
1080  */
1081     static int
json_decode_all(js_read_T * reader,typval_T * res,int options)1082 json_decode_all(js_read_T *reader, typval_T *res, int options)
1083 {
1084     int ret;
1085 
1086     // We find the end once, to avoid calling strlen() many times.
1087     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1088     json_skip_white(reader);
1089     ret = json_decode_item(reader, res, options);
1090     if (ret != OK)
1091     {
1092 	if (ret == MAYBE)
1093 	    semsg(_(e_json_error), reader->js_buf);
1094 	return FAIL;
1095     }
1096     json_skip_white(reader);
1097     if (reader->js_buf[reader->js_used] != NUL)
1098     {
1099 	semsg(_(e_trailing_arg), reader->js_buf + reader->js_used);
1100 	return FAIL;
1101     }
1102     return OK;
1103 }
1104 
1105 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
1106 /*
1107  * Decode the JSON from "reader" and store the result in "res".
1108  * "options" can be JSON_JS or zero;
1109  * Return FAIL for a decoding error.
1110  * Return MAYBE for an incomplete message.
1111  * Consumes the message anyway.
1112  */
1113     int
json_decode(js_read_T * reader,typval_T * res,int options)1114 json_decode(js_read_T *reader, typval_T *res, int options)
1115 {
1116     int ret;
1117 
1118     // We find the end once, to avoid calling strlen() many times.
1119     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1120     json_skip_white(reader);
1121     ret = json_decode_item(reader, res, options);
1122     json_skip_white(reader);
1123 
1124     return ret;
1125 }
1126 #endif
1127 
1128 /*
1129  * Decode the JSON from "reader" to find the end of the message.
1130  * "options" can be JSON_JS or zero.
1131  * This is only used for testing.
1132  * Return FAIL if the message has a decoding error.
1133  * Return MAYBE if the message is truncated, need to read more.
1134  * This only works reliable if the message contains an object, array or
1135  * string.  A number might be truncated without knowing.
1136  * Does not advance the reader.
1137  */
1138     int
json_find_end(js_read_T * reader,int options)1139 json_find_end(js_read_T *reader, int options)
1140 {
1141     int used_save = reader->js_used;
1142     int ret;
1143 
1144     // We find the end once, to avoid calling strlen() many times.
1145     reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
1146     json_skip_white(reader);
1147     ret = json_decode_item(reader, NULL, options);
1148     reader->js_used = used_save;
1149     return ret;
1150 }
1151 
1152 /*
1153  * "js_decode()" function
1154  */
1155     void
f_js_decode(typval_T * argvars,typval_T * rettv)1156 f_js_decode(typval_T *argvars, typval_T *rettv)
1157 {
1158     js_read_T	reader;
1159 
1160     if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
1161 	return;
1162 
1163     reader.js_buf = tv_get_string(&argvars[0]);
1164     reader.js_fill = NULL;
1165     reader.js_used = 0;
1166     if (json_decode_all(&reader, rettv, JSON_JS) != OK)
1167 	emsg(_(e_invarg));
1168 }
1169 
1170 /*
1171  * "js_encode()" function
1172  */
1173     void
f_js_encode(typval_T * argvars,typval_T * rettv)1174 f_js_encode(typval_T *argvars, typval_T *rettv)
1175 {
1176     rettv->v_type = VAR_STRING;
1177     rettv->vval.v_string = json_encode(&argvars[0], JSON_JS);
1178 }
1179 
1180 /*
1181  * "json_decode()" function
1182  */
1183     void
f_json_decode(typval_T * argvars,typval_T * rettv)1184 f_json_decode(typval_T *argvars, typval_T *rettv)
1185 {
1186     js_read_T	reader;
1187 
1188     if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
1189 	return;
1190 
1191     reader.js_buf = tv_get_string(&argvars[0]);
1192     reader.js_fill = NULL;
1193     reader.js_used = 0;
1194     json_decode_all(&reader, rettv, 0);
1195 }
1196 
1197 /*
1198  * "json_encode()" function
1199  */
1200     void
f_json_encode(typval_T * argvars,typval_T * rettv)1201 f_json_encode(typval_T *argvars, typval_T *rettv)
1202 {
1203     rettv->v_type = VAR_STRING;
1204     rettv->vval.v_string = json_encode(&argvars[0], 0);
1205 }
1206 #endif
1207