Mercurial > vim
comparison src/json.c @ 10559:4d8be28b5913 v8.0.0169
patch 8.0.0169: json_decode() may run out of stack space
commit https://github.com/vim/vim/commit/8b2f19536ff979046f0d241850f4176a1ce4bca9
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Jan 10 19:44:18 2017 +0100
patch 8.0.0169: json_decode() may run out of stack space
Problem: For complicated string json_decode() may run out of stack space.
Solution: Change the recursive solution into an iterative solution.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 10 Jan 2017 19:45:03 +0100 |
parents | f83b6a0b6148 |
children | e025378406d1 |
comparison
equal
deleted
inserted
replaced
10558:eb3603e558be | 10559:4d8be28b5913 |
---|---|
376 } | 376 } |
377 fill_numbuflen(reader); | 377 fill_numbuflen(reader); |
378 } | 378 } |
379 | 379 |
380 static int | 380 static int |
381 json_decode_array(js_read_T *reader, typval_T *res, int options) | |
382 { | |
383 char_u *p; | |
384 typval_T item; | |
385 listitem_T *li; | |
386 int ret; | |
387 | |
388 if (res != NULL && rettv_list_alloc(res) == FAIL) | |
389 { | |
390 res->v_type = VAR_SPECIAL; | |
391 res->vval.v_number = VVAL_NONE; | |
392 return FAIL; | |
393 } | |
394 ++reader->js_used; /* consume the '[' */ | |
395 | |
396 while (TRUE) | |
397 { | |
398 json_skip_white(reader); | |
399 p = reader->js_buf + reader->js_used; | |
400 if (*p == NUL) | |
401 return MAYBE; | |
402 if (*p == ']') | |
403 { | |
404 ++reader->js_used; /* consume the ']' */ | |
405 break; | |
406 } | |
407 | |
408 ret = json_decode_item(reader, res == NULL ? NULL : &item, options); | |
409 if (ret != OK) | |
410 return ret; | |
411 if (res != NULL) | |
412 { | |
413 li = listitem_alloc(); | |
414 if (li == NULL) | |
415 { | |
416 clear_tv(&item); | |
417 return FAIL; | |
418 } | |
419 li->li_tv = item; | |
420 list_append(res->vval.v_list, li); | |
421 } | |
422 | |
423 json_skip_white(reader); | |
424 p = reader->js_buf + reader->js_used; | |
425 if (*p == ',') | |
426 ++reader->js_used; | |
427 else if (*p != ']') | |
428 { | |
429 if (*p == NUL) | |
430 return MAYBE; | |
431 EMSG(_(e_invarg)); | |
432 return FAIL; | |
433 } | |
434 } | |
435 return OK; | |
436 } | |
437 | |
438 static int | |
439 json_decode_object(js_read_T *reader, typval_T *res, int options) | |
440 { | |
441 char_u *p; | |
442 typval_T tvkey; | |
443 typval_T item; | |
444 dictitem_T *di; | |
445 char_u buf[NUMBUFLEN]; | |
446 char_u *key = NULL; | |
447 int ret; | |
448 | |
449 if (res != NULL && rettv_dict_alloc(res) == FAIL) | |
450 { | |
451 res->v_type = VAR_SPECIAL; | |
452 res->vval.v_number = VVAL_NONE; | |
453 return FAIL; | |
454 } | |
455 ++reader->js_used; /* consume the '{' */ | |
456 | |
457 while (TRUE) | |
458 { | |
459 json_skip_white(reader); | |
460 p = reader->js_buf + reader->js_used; | |
461 if (*p == NUL) | |
462 return MAYBE; | |
463 if (*p == '}') | |
464 { | |
465 ++reader->js_used; /* consume the '}' */ | |
466 break; | |
467 } | |
468 | |
469 if ((options & JSON_JS) && reader->js_buf[reader->js_used] != '"') | |
470 { | |
471 /* accept a key that is not in quotes */ | |
472 key = p = reader->js_buf + reader->js_used; | |
473 while (*p != NUL && *p != ':' && *p > ' ') | |
474 ++p; | |
475 tvkey.v_type = VAR_STRING; | |
476 tvkey.vval.v_string = vim_strnsave(key, (int)(p - key)); | |
477 reader->js_used += (int)(p - key); | |
478 key = tvkey.vval.v_string; | |
479 } | |
480 else | |
481 { | |
482 ret = json_decode_item(reader, res == NULL ? NULL : &tvkey, | |
483 options); | |
484 if (ret != OK) | |
485 return ret; | |
486 if (res != NULL) | |
487 { | |
488 key = get_tv_string_buf_chk(&tvkey, buf); | |
489 if (key == NULL || *key == NUL) | |
490 { | |
491 clear_tv(&tvkey); | |
492 EMSG(_(e_invarg)); | |
493 return FAIL; | |
494 } | |
495 } | |
496 } | |
497 | |
498 json_skip_white(reader); | |
499 p = reader->js_buf + reader->js_used; | |
500 if (*p != ':') | |
501 { | |
502 if (res != NULL) | |
503 clear_tv(&tvkey); | |
504 if (*p == NUL) | |
505 return MAYBE; | |
506 EMSG(_(e_invarg)); | |
507 return FAIL; | |
508 } | |
509 ++reader->js_used; | |
510 json_skip_white(reader); | |
511 | |
512 ret = json_decode_item(reader, res == NULL ? NULL : &item, options); | |
513 if (ret != OK) | |
514 { | |
515 if (res != NULL) | |
516 clear_tv(&tvkey); | |
517 return ret; | |
518 } | |
519 | |
520 if (res != NULL && dict_find(res->vval.v_dict, key, -1) != NULL) | |
521 { | |
522 EMSG2(_("E937: Duplicate key in JSON: \"%s\""), key); | |
523 clear_tv(&tvkey); | |
524 clear_tv(&item); | |
525 return FAIL; | |
526 } | |
527 | |
528 if (res != NULL) | |
529 { | |
530 di = dictitem_alloc(key); | |
531 clear_tv(&tvkey); | |
532 if (di == NULL) | |
533 { | |
534 clear_tv(&item); | |
535 return FAIL; | |
536 } | |
537 di->di_tv = item; | |
538 di->di_tv.v_lock = 0; | |
539 if (dict_add(res->vval.v_dict, di) == FAIL) | |
540 { | |
541 dictitem_free(di); | |
542 return FAIL; | |
543 } | |
544 } | |
545 | |
546 json_skip_white(reader); | |
547 p = reader->js_buf + reader->js_used; | |
548 if (*p == ',') | |
549 ++reader->js_used; | |
550 else if (*p != '}') | |
551 { | |
552 if (*p == NUL) | |
553 return MAYBE; | |
554 EMSG(_(e_invarg)); | |
555 return FAIL; | |
556 } | |
557 } | |
558 return OK; | |
559 } | |
560 | |
561 static int | |
562 json_decode_string(js_read_T *reader, typval_T *res) | 381 json_decode_string(js_read_T *reader, typval_T *res) |
563 { | 382 { |
564 garray_T ga; | 383 garray_T ga; |
565 int len; | 384 int len; |
566 char_u *p; | 385 char_u *p; |
721 ga_clear(&ga); | 540 ga_clear(&ga); |
722 } | 541 } |
723 return MAYBE; | 542 return MAYBE; |
724 } | 543 } |
725 | 544 |
545 typedef enum { | |
546 JSON_ARRAY, /* parsing items in an array */ | |
547 JSON_OBJECT_KEY, /* parsing key of an object */ | |
548 JSON_OBJECT /* parsing item in an object, after the key */ | |
549 } json_decode_T; | |
550 | |
551 typedef struct { | |
552 json_decode_T jd_type; | |
553 typval_T jd_tv; /* the list or dict */ | |
554 typval_T jd_key_tv; | |
555 char_u *jd_key; | |
556 } json_dec_item_T; | |
557 | |
726 /* | 558 /* |
727 * Decode one item and put it in "res". If "res" is NULL only advance. | 559 * Decode one item and put it in "res". If "res" is NULL only advance. |
728 * Must already have skipped white space. | 560 * Must already have skipped white space. |
729 * | 561 * |
730 * Return FAIL for a decoding error (and give an error). | 562 * Return FAIL for a decoding error (and give an error). |
733 static int | 565 static int |
734 json_decode_item(js_read_T *reader, typval_T *res, int options) | 566 json_decode_item(js_read_T *reader, typval_T *res, int options) |
735 { | 567 { |
736 char_u *p; | 568 char_u *p; |
737 int len; | 569 int len; |
570 int retval; | |
571 garray_T stack; | |
572 typval_T item; | |
573 typval_T *cur_item; | |
574 json_dec_item_T *top_item; | |
575 char_u key_buf[NUMBUFLEN]; | |
576 | |
577 ga_init2(&stack, sizeof(json_dec_item_T), 100); | |
578 cur_item = res; | |
579 init_tv(&item); | |
738 | 580 |
739 fill_numbuflen(reader); | 581 fill_numbuflen(reader); |
740 p = reader->js_buf + reader->js_used; | 582 p = reader->js_buf + reader->js_used; |
741 switch (*p) | 583 for (;;) |
742 { | 584 { |
743 case '[': /* array */ | 585 top_item = NULL; |
744 return json_decode_array(reader, res, options); | 586 if (stack.ga_len > 0) |
745 | 587 { |
746 case '{': /* object */ | 588 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; |
747 return json_decode_object(reader, res, options); | 589 json_skip_white(reader); |
748 | 590 p = reader->js_buf + reader->js_used; |
749 case '"': /* string */ | 591 if (*p == NUL) |
750 return json_decode_string(reader, res); | 592 { |
751 | 593 retval = MAYBE; |
752 case ',': /* comma: empty item */ | 594 if (top_item->jd_type == JSON_OBJECT) |
753 if ((options & JSON_JS) == 0) | 595 /* did get the key, clear it */ |
754 { | 596 clear_tv(&top_item->jd_key_tv); |
755 EMSG(_(e_invarg)); | 597 goto theend; |
756 return FAIL; | 598 } |
757 } | 599 if (top_item->jd_type == JSON_OBJECT_KEY |
758 /* FALLTHROUGH */ | 600 || top_item->jd_type == JSON_ARRAY) |
759 case NUL: /* empty */ | 601 { |
760 if (res != NULL) | 602 /* Check for end of object or array. */ |
761 { | 603 if (*p == (top_item->jd_type == JSON_ARRAY ? ']' : '}')) |
762 res->v_type = VAR_SPECIAL; | 604 { |
763 res->vval.v_number = VVAL_NONE; | 605 ++reader->js_used; /* consume the ']' or '}' */ |
764 } | 606 --stack.ga_len; |
765 return OK; | 607 if (stack.ga_len == 0) |
766 | 608 { |
767 default: | 609 retval = OK; |
768 if (VIM_ISDIGIT(*p) || *p == '-') | 610 goto theend; |
769 { | 611 } |
612 if (cur_item != NULL) | |
613 cur_item = &top_item->jd_tv; | |
614 goto item_end; | |
615 } | |
616 } | |
617 } | |
618 | |
619 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY | |
620 && (options & JSON_JS) | |
621 && reader->js_buf[reader->js_used] != '"') | |
622 { | |
623 char_u *key; | |
624 | |
625 /* accept an object key that is not in quotes */ | |
626 key = p = reader->js_buf + reader->js_used; | |
627 while (*p != NUL && *p != ':' && *p > ' ') | |
628 ++p; | |
629 cur_item->v_type = VAR_STRING; | |
630 cur_item->vval.v_string = vim_strnsave(key, (int)(p - key)); | |
631 reader->js_used += (int)(p - key); | |
632 top_item->jd_key = cur_item->vval.v_string; | |
633 } | |
634 else | |
635 { | |
636 switch (*p) | |
637 { | |
638 case '[': /* start of array */ | |
639 if (ga_grow(&stack, 1) == FAIL) | |
640 { | |
641 retval = FAIL; | |
642 break; | |
643 } | |
644 if (cur_item != NULL && rettv_list_alloc(cur_item) == FAIL) | |
645 { | |
646 cur_item->v_type = VAR_SPECIAL; | |
647 cur_item->vval.v_number = VVAL_NONE; | |
648 retval = FAIL; | |
649 break; | |
650 } | |
651 | |
652 ++reader->js_used; /* consume the '[' */ | |
653 top_item = ((json_dec_item_T *)stack.ga_data) | |
654 + stack.ga_len; | |
655 top_item->jd_type = JSON_ARRAY; | |
656 ++stack.ga_len; | |
657 if (cur_item != NULL) | |
658 { | |
659 top_item->jd_tv = *cur_item; | |
660 cur_item = &item; | |
661 } | |
662 continue; | |
663 | |
664 case '{': /* start of object */ | |
665 if (ga_grow(&stack, 1) == FAIL) | |
666 { | |
667 retval = FAIL; | |
668 break; | |
669 } | |
670 if (cur_item != NULL && rettv_dict_alloc(cur_item) == FAIL) | |
671 { | |
672 cur_item->v_type = VAR_SPECIAL; | |
673 cur_item->vval.v_number = VVAL_NONE; | |
674 retval = FAIL; | |
675 break; | |
676 } | |
677 | |
678 ++reader->js_used; /* consume the '{' */ | |
679 top_item = ((json_dec_item_T *)stack.ga_data) | |
680 + stack.ga_len; | |
681 top_item->jd_type = JSON_OBJECT_KEY; | |
682 ++stack.ga_len; | |
683 if (cur_item != NULL) | |
684 { | |
685 top_item->jd_tv = *cur_item; | |
686 cur_item = &top_item->jd_key_tv; | |
687 } | |
688 continue; | |
689 | |
690 case '"': /* string */ | |
691 retval = json_decode_string(reader, cur_item); | |
692 break; | |
693 | |
694 case ',': /* comma: empty item */ | |
695 if ((options & JSON_JS) == 0) | |
696 { | |
697 EMSG(_(e_invarg)); | |
698 retval = FAIL; | |
699 break; | |
700 } | |
701 /* FALLTHROUGH */ | |
702 case NUL: /* empty */ | |
703 if (cur_item != NULL) | |
704 { | |
705 cur_item->v_type = VAR_SPECIAL; | |
706 cur_item->vval.v_number = VVAL_NONE; | |
707 } | |
708 retval = OK; | |
709 break; | |
710 | |
711 default: | |
712 if (VIM_ISDIGIT(*p) || *p == '-') | |
713 { | |
770 #ifdef FEAT_FLOAT | 714 #ifdef FEAT_FLOAT |
771 char_u *sp = p; | 715 char_u *sp = p; |
772 | 716 |
773 if (*sp == '-') | 717 if (*sp == '-') |
774 { | 718 { |
775 ++sp; | 719 ++sp; |
776 if (*sp == NUL) | 720 if (*sp == NUL) |
777 return MAYBE; | 721 { |
778 if (!VIM_ISDIGIT(*sp)) | 722 retval = MAYBE; |
723 break; | |
724 } | |
725 if (!VIM_ISDIGIT(*sp)) | |
726 { | |
727 EMSG(_(e_invarg)); | |
728 retval = FAIL; | |
729 break; | |
730 } | |
731 } | |
732 sp = skipdigits(sp); | |
733 if (*sp == '.' || *sp == 'e' || *sp == 'E') | |
734 { | |
735 if (cur_item == NULL) | |
736 { | |
737 float_T f; | |
738 | |
739 len = string2float(p, &f); | |
740 } | |
741 else | |
742 { | |
743 cur_item->v_type = VAR_FLOAT; | |
744 len = string2float(p, &cur_item->vval.v_float); | |
745 } | |
746 } | |
747 else | |
748 #endif | |
749 { | |
750 varnumber_T nr; | |
751 | |
752 vim_str2nr(reader->js_buf + reader->js_used, | |
753 NULL, &len, 0, /* what */ | |
754 &nr, NULL, 0); | |
755 if (cur_item != NULL) | |
756 { | |
757 cur_item->v_type = VAR_NUMBER; | |
758 cur_item->vval.v_number = nr; | |
759 } | |
760 } | |
761 reader->js_used += len; | |
762 retval = OK; | |
763 break; | |
764 } | |
765 if (STRNICMP((char *)p, "false", 5) == 0) | |
766 { | |
767 reader->js_used += 5; | |
768 if (cur_item != NULL) | |
769 { | |
770 cur_item->v_type = VAR_SPECIAL; | |
771 cur_item->vval.v_number = VVAL_FALSE; | |
772 } | |
773 retval = OK; | |
774 break; | |
775 } | |
776 if (STRNICMP((char *)p, "true", 4) == 0) | |
777 { | |
778 reader->js_used += 4; | |
779 if (cur_item != NULL) | |
780 { | |
781 cur_item->v_type = VAR_SPECIAL; | |
782 cur_item->vval.v_number = VVAL_TRUE; | |
783 } | |
784 retval = OK; | |
785 break; | |
786 } | |
787 if (STRNICMP((char *)p, "null", 4) == 0) | |
788 { | |
789 reader->js_used += 4; | |
790 if (cur_item != NULL) | |
791 { | |
792 cur_item->v_type = VAR_SPECIAL; | |
793 cur_item->vval.v_number = VVAL_NULL; | |
794 } | |
795 retval = OK; | |
796 break; | |
797 } | |
798 #ifdef FEAT_FLOAT | |
799 if (STRNICMP((char *)p, "NaN", 3) == 0) | |
800 { | |
801 reader->js_used += 3; | |
802 if (cur_item != NULL) | |
803 { | |
804 cur_item->v_type = VAR_FLOAT; | |
805 cur_item->vval.v_float = NAN; | |
806 } | |
807 retval = OK; | |
808 break; | |
809 } | |
810 if (STRNICMP((char *)p, "Infinity", 8) == 0) | |
811 { | |
812 reader->js_used += 8; | |
813 if (cur_item != NULL) | |
814 { | |
815 cur_item->v_type = VAR_FLOAT; | |
816 cur_item->vval.v_float = INFINITY; | |
817 } | |
818 retval = OK; | |
819 break; | |
820 } | |
821 #endif | |
822 /* check for truncated name */ | |
823 len = (int)(reader->js_end - (reader->js_buf + reader->js_used)); | |
824 if ( | |
825 (len < 5 && STRNICMP((char *)p, "false", len) == 0) | |
826 #ifdef FEAT_FLOAT | |
827 || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0) | |
828 || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0) | |
829 #endif | |
830 || (len < 4 && (STRNICMP((char *)p, "true", len) == 0 | |
831 || STRNICMP((char *)p, "null", len) == 0))) | |
832 | |
833 retval = MAYBE; | |
834 else | |
835 retval = FAIL; | |
836 break; | |
837 } | |
838 | |
839 /* We are finished when retval is FAIL or MAYBE and when at the | |
840 * toplevel. */ | |
841 if (retval == FAIL) | |
842 break; | |
843 if (retval == MAYBE || stack.ga_len == 0) | |
844 goto theend; | |
845 | |
846 if (top_item != NULL && top_item->jd_type == JSON_OBJECT_KEY | |
847 && cur_item != NULL) | |
848 { | |
849 top_item->jd_key = get_tv_string_buf_chk(cur_item, key_buf); | |
850 if (top_item->jd_key == NULL || *top_item->jd_key == NUL) | |
851 { | |
852 clear_tv(cur_item); | |
853 EMSG(_(e_invarg)); | |
854 retval = FAIL; | |
855 goto theend; | |
856 } | |
857 } | |
858 } | |
859 | |
860 item_end: | |
861 top_item = ((json_dec_item_T *)stack.ga_data) + stack.ga_len - 1; | |
862 switch (top_item->jd_type) | |
863 { | |
864 case JSON_ARRAY: | |
865 if (res != NULL) | |
866 { | |
867 listitem_T *li = listitem_alloc(); | |
868 | |
869 if (li == NULL) | |
870 { | |
871 clear_tv(cur_item); | |
872 retval = FAIL; | |
873 goto theend; | |
874 } | |
875 li->li_tv = *cur_item; | |
876 list_append(top_item->jd_tv.vval.v_list, li); | |
877 } | |
878 if (cur_item != NULL) | |
879 cur_item = &item; | |
880 | |
881 json_skip_white(reader); | |
882 p = reader->js_buf + reader->js_used; | |
883 if (*p == ',') | |
884 ++reader->js_used; | |
885 else if (*p != ']') | |
886 { | |
887 if (*p == NUL) | |
888 retval = MAYBE; | |
889 else | |
779 { | 890 { |
780 EMSG(_(e_invarg)); | 891 EMSG(_(e_invarg)); |
781 return FAIL; | 892 retval = FAIL; |
782 } | 893 } |
783 } | 894 goto theend; |
784 sp = skipdigits(sp); | 895 } |
785 if (*sp == '.' || *sp == 'e' || *sp == 'E') | 896 break; |
786 { | 897 |
787 if (res == NULL) | 898 case JSON_OBJECT_KEY: |
788 { | 899 json_skip_white(reader); |
789 float_T f; | 900 p = reader->js_buf + reader->js_used; |
790 | 901 if (*p != ':') |
791 len = string2float(p, &f); | 902 { |
792 } | 903 if (cur_item != NULL) |
904 clear_tv(cur_item); | |
905 if (*p == NUL) | |
906 retval = MAYBE; | |
793 else | 907 else |
794 { | 908 { |
795 res->v_type = VAR_FLOAT; | 909 EMSG(_(e_invarg)); |
796 len = string2float(p, &res->vval.v_float); | 910 retval = FAIL; |
797 } | 911 } |
798 } | 912 goto theend; |
799 else | 913 } |
800 #endif | 914 ++reader->js_used; |
801 { | 915 json_skip_white(reader); |
802 varnumber_T nr; | 916 top_item->jd_type = JSON_OBJECT; |
803 | 917 if (cur_item != NULL) |
804 vim_str2nr(reader->js_buf + reader->js_used, | 918 cur_item = &item; |
805 NULL, &len, 0, /* what */ | 919 break; |
806 &nr, NULL, 0); | 920 |
807 if (res != NULL) | 921 case JSON_OBJECT: |
808 { | 922 if (cur_item != NULL |
809 res->v_type = VAR_NUMBER; | 923 && dict_find(top_item->jd_tv.vval.v_dict, |
810 res->vval.v_number = nr; | 924 top_item->jd_key, -1) != NULL) |
811 } | 925 { |
812 } | 926 EMSG2(_("E937: Duplicate key in JSON: \"%s\""), |
813 reader->js_used += len; | 927 top_item->jd_key); |
814 return OK; | 928 clear_tv(&top_item->jd_key_tv); |
815 } | 929 clear_tv(cur_item); |
816 if (STRNICMP((char *)p, "false", 5) == 0) | 930 retval = FAIL; |
817 { | 931 goto theend; |
818 reader->js_used += 5; | 932 } |
819 if (res != NULL) | 933 |
820 { | 934 if (cur_item != NULL) |
821 res->v_type = VAR_SPECIAL; | 935 { |
822 res->vval.v_number = VVAL_FALSE; | 936 dictitem_T *di = dictitem_alloc(top_item->jd_key); |
823 } | 937 |
824 return OK; | 938 clear_tv(&top_item->jd_key_tv); |
825 } | 939 if (di == NULL) |
826 if (STRNICMP((char *)p, "true", 4) == 0) | 940 { |
827 { | 941 clear_tv(cur_item); |
828 reader->js_used += 4; | 942 retval = FAIL; |
829 if (res != NULL) | 943 goto theend; |
830 { | 944 } |
831 res->v_type = VAR_SPECIAL; | 945 di->di_tv = *cur_item; |
832 res->vval.v_number = VVAL_TRUE; | 946 di->di_tv.v_lock = 0; |
833 } | 947 if (dict_add(top_item->jd_tv.vval.v_dict, di) == FAIL) |
834 return OK; | 948 { |
835 } | 949 dictitem_free(di); |
836 if (STRNICMP((char *)p, "null", 4) == 0) | 950 retval = FAIL; |
837 { | 951 goto theend; |
838 reader->js_used += 4; | 952 } |
839 if (res != NULL) | 953 } |
840 { | 954 |
841 res->v_type = VAR_SPECIAL; | 955 json_skip_white(reader); |
842 res->vval.v_number = VVAL_NULL; | 956 p = reader->js_buf + reader->js_used; |
843 } | 957 if (*p == ',') |
844 return OK; | 958 ++reader->js_used; |
845 } | 959 else if (*p != '}') |
846 #ifdef FEAT_FLOAT | 960 { |
847 if (STRNICMP((char *)p, "NaN", 3) == 0) | 961 if (*p == NUL) |
848 { | 962 retval = MAYBE; |
849 reader->js_used += 3; | 963 else |
850 if (res != NULL) | 964 { |
851 { | 965 EMSG(_(e_invarg)); |
852 res->v_type = VAR_FLOAT; | 966 retval = FAIL; |
853 res->vval.v_float = NAN; | 967 } |
854 } | 968 goto theend; |
855 return OK; | 969 } |
856 } | 970 top_item->jd_type = JSON_OBJECT_KEY; |
857 if (STRNICMP((char *)p, "Infinity", 8) == 0) | 971 if (cur_item != NULL) |
858 { | 972 cur_item = &top_item->jd_key_tv; |
859 reader->js_used += 8; | 973 break; |
860 if (res != NULL) | 974 } |
861 { | 975 } |
862 res->v_type = VAR_FLOAT; | 976 |
863 res->vval.v_float = INFINITY; | 977 /* Get here when parsing failed. */ |
864 } | |
865 return OK; | |
866 } | |
867 #endif | |
868 /* check for truncated name */ | |
869 len = (int)(reader->js_end - (reader->js_buf + reader->js_used)); | |
870 if ( | |
871 (len < 5 && STRNICMP((char *)p, "false", len) == 0) | |
872 #ifdef FEAT_FLOAT | |
873 || (len < 8 && STRNICMP((char *)p, "Infinity", len) == 0) | |
874 || (len < 3 && STRNICMP((char *)p, "NaN", len) == 0) | |
875 #endif | |
876 || (len < 4 && (STRNICMP((char *)p, "true", len) == 0 | |
877 || STRNICMP((char *)p, "null", len) == 0))) | |
878 return MAYBE; | |
879 break; | |
880 } | |
881 | |
882 if (res != NULL) | 978 if (res != NULL) |
883 { | 979 { |
980 clear_tv(res); | |
884 res->v_type = VAR_SPECIAL; | 981 res->v_type = VAR_SPECIAL; |
885 res->vval.v_number = VVAL_NONE; | 982 res->vval.v_number = VVAL_NONE; |
886 } | 983 } |
887 EMSG(_(e_invarg)); | 984 EMSG(_(e_invarg)); |
888 return FAIL; | 985 |
986 theend: | |
987 ga_clear(&stack); | |
988 clear_tv(&item); | |
989 return retval; | |
889 } | 990 } |
890 | 991 |
891 /* | 992 /* |
892 * Decode the JSON from "reader" and store the result in "res". | 993 * Decode the JSON from "reader" and store the result in "res". |
893 * "options" can be JSON_JS or zero; | 994 * "options" can be JSON_JS or zero; |