Changeset 74173 in vbox for trunk/src/VBox/Runtime/common/misc/json.cpp
- Timestamp:
- Sep 10, 2018 9:39:10 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/json.cpp
r74170 r74173 367 367 DECLINLINE(char) rtJsonTokenizerPeekCh(PRTJSONTOKENIZER pTokenizer) 368 368 { 369 return rtJsonTokenizerIsEos(pTokenizer)370 ? '\0'371 : pTokenizer->achBuf[pTokenizer->offBuf + 1]; /** @todo Read out of bounds */369 return !rtJsonTokenizerIsEos(pTokenizer) 370 ? pTokenizer->achBuf[pTokenizer->offBuf + 1] /** @todo Read out of bounds */ 371 : '\0'; 372 372 } 373 373 … … 383 383 char ch; 384 384 385 if (rtJsonTokenizerIsEos(pTokenizer)) 385 if (!rtJsonTokenizerIsEos(pTokenizer)) 386 ch = pTokenizer->achBuf[pTokenizer->offBuf]; 387 else 386 388 ch = '\0'; 387 else388 ch = pTokenizer->achBuf[pTokenizer->offBuf];389 389 390 390 return ch; … … 604 604 static int rtJsonTokenizerGetString(PRTJSONTOKENIZER pTokenizer, PRTJSONTOKEN pToken) 605 605 { 606 int rc = VINF_SUCCESS; 607 size_t cchStr = 0; 608 size_t cchStrMax = _4K; 609 char *pszTmp = (char *)RTMemAllocZ(cchStrMax * sizeof(char)); 610 if (RT_UNLIKELY(!pszTmp)) 611 return VERR_NO_STR_MEMORY; 612 613 RT_BZERO(pszTmp, cchStrMax); 606 size_t cchStrMax = 64; 607 char *pszDecoded = (char *)RTStrAlloc(cchStrMax); 608 AssertReturn(pszDecoded, VERR_NO_STR_MEMORY); 614 609 615 610 Assert(rtJsonTokenizerGetCh(pTokenizer) == '\"'); … … 619 614 pToken->Pos = pTokenizer->Pos; 620 615 616 size_t cchStr = 0; 621 617 char ch = rtJsonTokenizerGetCh(pTokenizer); 622 618 while ( ch != '\"' 623 && ch != '\0' 624 && RT_SUCCESS(rc)) 625 { 626 if (ch == '\\') 619 && ch != '\0') 620 { 621 if (ch != '\\') 622 { 623 pszDecoded[cchStr++] = ch; 624 rtJsonTokenizerSkipCh(pTokenizer); 625 } 626 else 627 627 { 628 628 /* Escape sequence, check the next character */ … … 632 632 { 633 633 case '\"': 634 pszTmp[cchStr] = '\"'; 634 pszDecoded[cchStr++] = '\"'; 635 rtJsonTokenizerSkipCh(pTokenizer); 635 636 break; 636 637 case '\\': 637 pszTmp[cchStr] = '\\'; 638 pszDecoded[cchStr++] = '\\'; 639 rtJsonTokenizerSkipCh(pTokenizer); 638 640 break; 639 641 case '/': 640 pszTmp[cchStr] = '/'; 642 pszDecoded[cchStr++] = '/'; 643 rtJsonTokenizerSkipCh(pTokenizer); 641 644 break; 642 645 case '\b': 643 pszTmp[cchStr] = '\b'; 646 pszDecoded[cchStr++] = '\b'; 647 rtJsonTokenizerSkipCh(pTokenizer); 644 648 break; 645 649 case '\n': 646 pszTmp[cchStr] = '\n'; 650 pszDecoded[cchStr++] = '\n'; 651 rtJsonTokenizerSkipCh(pTokenizer); 647 652 break; 648 653 case '\f': 649 pszTmp[cchStr] = '\f'; 654 pszDecoded[cchStr++] = '\f'; 655 rtJsonTokenizerSkipCh(pTokenizer); 650 656 break; 651 657 case '\r': 652 pszTmp[cchStr] = '\r'; 658 pszDecoded[cchStr++] = '\r'; 659 rtJsonTokenizerSkipCh(pTokenizer); 653 660 break; 654 661 case '\t': 655 pszTmp[cchStr] = '\t'; 662 pszDecoded[cchStr++] = '\t'; 663 rtJsonTokenizerSkipCh(pTokenizer); 656 664 break; 657 665 case 'u': 658 rc = VERR_NOT_SUPPORTED; 659 break; 666 { 667 /* \uXXXX */ 668 int rc = VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE; 669 rtJsonTokenizerSkipCh(pTokenizer); 670 char chX1 = rtJsonTokenizerGetCh(pTokenizer); 671 if (RT_C_IS_XDIGIT(chX1)) 672 { 673 rtJsonTokenizerSkipCh(pTokenizer); 674 char chX2 = rtJsonTokenizerGetCh(pTokenizer); 675 if (RT_C_IS_XDIGIT(chX2)) 676 { 677 rtJsonTokenizerSkipCh(pTokenizer); 678 char chX3 = rtJsonTokenizerGetCh(pTokenizer); 679 if (RT_C_IS_XDIGIT(chX3)) 680 { 681 rtJsonTokenizerSkipCh(pTokenizer); 682 char chX4 = rtJsonTokenizerGetCh(pTokenizer); 683 if (RT_C_IS_XDIGIT(chX4)) 684 { 685 rtJsonTokenizerSkipCh(pTokenizer); 686 687 RTUNICP uc = ((RTUTF16)(chX1 <= '9' ? chX1 - '0' : (chX1 & 7) + 9) << 12) 688 | ((RTUTF16)(chX2 <= '9' ? chX2 - '0' : (chX2 & 7) + 9) << 8) 689 | ((RTUTF16)(chX3 <= '9' ? chX3 - '0' : (chX3 & 7) + 9) << 4) 690 | ((RTUTF16)(chX4 <= '9' ? chX4 - '0' : (chX4 & 7) + 9)); 691 if ( !RTUtf16IsHighSurrogate((RTUTF16)uc) 692 && !RTUtf16IsLowSurrogate((RTUTF16)uc)) 693 rc = VINF_SUCCESS; 694 else if (RTUtf16IsHighSurrogate((RTUTF16)uc)) 695 { 696 /* The must be a low surrogate pair following the high one: */ 697 ch = rtJsonTokenizerGetCh(pTokenizer); 698 if (ch == '\\') 699 rtJsonTokenizerSkipCh(pTokenizer); 700 else 701 rc = VERR_JSON_MISSING_SURROGATE_PAIR; 702 ch = rtJsonTokenizerGetCh(pTokenizer); 703 if (ch == 'u') 704 rtJsonTokenizerSkipCh(pTokenizer); 705 else 706 rc = VERR_JSON_MISSING_SURROGATE_PAIR; 707 chX1 = rtJsonTokenizerGetCh(pTokenizer); 708 if (RT_C_IS_XDIGIT(chX1)) 709 rtJsonTokenizerSkipCh(pTokenizer); 710 else if (RT_SUCCESS_NP(rc)) 711 rc = VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE; 712 chX2 = rtJsonTokenizerGetCh(pTokenizer); 713 if (RT_C_IS_XDIGIT(chX2)) 714 rtJsonTokenizerSkipCh(pTokenizer); 715 else if (RT_SUCCESS_NP(rc)) 716 rc = VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE; 717 chX3 = rtJsonTokenizerGetCh(pTokenizer); 718 if (RT_C_IS_XDIGIT(chX3)) 719 rtJsonTokenizerSkipCh(pTokenizer); 720 else if (RT_SUCCESS_NP(rc)) 721 rc = VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE; 722 chX4 = rtJsonTokenizerGetCh(pTokenizer); 723 if (RT_C_IS_XDIGIT(chX4)) 724 rtJsonTokenizerSkipCh(pTokenizer); 725 else if (RT_SUCCESS_NP(rc)) 726 rc = VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE; 727 if (RT_SUCCESS(rc)) 728 { 729 RTUTF16 wc2 = ((RTUTF16)(chX1 <= '9' ? chX1 - '0' : (chX1 & 7) + 9) << 12) 730 | ((RTUTF16)(chX2 <= '9' ? chX2 - '0' : (chX2 & 7) + 9) << 8) 731 | ((RTUTF16)(chX3 <= '9' ? chX3 - '0' : (chX3 & 7) + 9) << 4) 732 | ((RTUTF16)(chX4 <= '9' ? chX4 - '0' : (chX4 & 7) + 9)); 733 if (RTUtf16IsLowSurrogate(wc2)) 734 uc = 0x10000 + (((uc & 0x3ff) << 10) | (wc2 & 0x3ff)); 735 else 736 rc = VERR_JSON_BAD_SURROGATE_PAIR_SEQUENCE; 737 } 738 } 739 else 740 rc = VERR_JSON_BAD_SURROGATE_PAIR_SEQUENCE; 741 if (RT_SUCCESS(rc)) 742 { 743 Assert(cchStr + RTStrCpSize(uc) < cchStrMax); 744 char *pszNext = RTStrPutCp(&pszDecoded[cchStr], uc); 745 Assert((size_t)(pszNext - &pszDecoded[cchStr]) == RTStrCpSize(uc)); 746 cchStr += pszNext - &pszDecoded[cchStr]; 747 break; 748 } 749 } 750 } 751 } 752 } 753 RTStrFree(pszDecoded); 754 if (rc == VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE) 755 rc = RTErrInfoSetF(pTokenizer->pErrInfo, rc, "Invalid \u escape sequence (line %zu col %zu)", 756 pTokenizer->Pos.iLine, pTokenizer->Pos.iChStart); 757 else if (rc == VERR_JSON_MISSING_SURROGATE_PAIR) 758 rc = RTErrInfoSetF(pTokenizer->pErrInfo, rc, "Missing UTF-16 surrogate pair (line %zu col %zu)", 759 pTokenizer->Pos.iLine, pTokenizer->Pos.iChStart); 760 else 761 rc = RTErrInfoSetF(pTokenizer->pErrInfo, rc, "Invalid UTF-16 surrogate pair (line %zu col %zu)", 762 pTokenizer->Pos.iLine, pTokenizer->Pos.iChStart); 763 return rc; 764 } 765 660 766 default: 661 rc = RTErrInfoSetF(pTokenizer->pErrInfo, VERR_JSON_MALFORMED, "bad escape sequence (line %zu col %zu)",662 pTokenizer->Pos.iLine, pTokenizer->Pos.iChStart);663 break;767 RTStrFree(pszDecoded); 768 return RTErrInfoSetF(pTokenizer->pErrInfo, VERR_JSON_MALFORMED, "bad escape sequence (line %zu col %zu)", 769 pTokenizer->Pos.iLine, pTokenizer->Pos.iChStart); 664 770 } 665 771 } 772 773 774 if (cchStr < cchStrMax - 4) 775 { /* likely */ } 666 776 else 667 pszTmp[cchStr] = ch;668 669 if (RT_FAILURE(rc))670 break;671 672 cchStr++;673 rtJsonTokenizerSkipCh(pTokenizer);674 if (cchStr == cchStrMax - 1)675 777 { 676 778 /* Increase string space. */ 677 size_t cchStrMaxNew = cchStrMax + _4K; 678 char *pszTmpNew = (char *)RTMemRealloc(pszTmp, cchStrMaxNew * sizeof(char)); 679 if (RT_UNLIKELY(!pszTmpNew)) 779 size_t cchStrMaxNew = cchStrMax < _4K ? cchStrMax * 2 : cchStrMax + _4K; 780 int rc = RTStrRealloc(&pszDecoded, cchStrMaxNew); 781 if (RT_SUCCESS(rc)) 782 cchStrMax = cchStrMaxNew; 783 else 680 784 { 681 rc = VERR_NO_STR_MEMORY;682 break;785 RTStrFree(pszDecoded); 786 return rc; 683 787 } 684 685 RT_BZERO(&pszTmpNew[cchStr], _4K);686 pszTmp = pszTmpNew;687 cchStrMax = cchStrMaxNew;688 788 } 689 789 ch = rtJsonTokenizerGetCh(pTokenizer); 690 790 } 691 791 692 if (RT_SUCCESS(rc)) 693 { 694 if (rtJsonTokenizerGetCh(pTokenizer) == '\"') 695 rtJsonTokenizerSkipCh(pTokenizer); /* Skip closing " */ 696 697 pToken->Class.String.pszStr = RTStrDupN(pszTmp, cchStr); 698 if (pToken->Class.String.pszStr) 699 pToken->Pos.iChEnd += cchStr; 700 else 701 rc = VERR_NO_STR_MEMORY; 702 } 703 704 if (pszTmp) 705 RTMemFree(pszTmp); 706 707 return rc; 792 if (ch == '\"') 793 rtJsonTokenizerSkipCh(pTokenizer); /* Skip closing " */ 794 795 Assert(cchStr < cchStrMax); 796 pszDecoded[cchStr] = '\0'; 797 if (cchStrMax - cchStr >= cchStrMax / 2) 798 RTStrRealloc(&pszDecoded, cchStr + 1); 799 pToken->Class.String.pszStr = pszDecoded; 800 801 pToken->Pos.iChEnd = pTokenizer->Pos.iChEnd; 802 return VINF_SUCCESS; 708 803 } 709 804
Note:
See TracChangeset
for help on using the changeset viewer.