- Timestamp:
- Jan 11, 2022 8:28:01 AM (3 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/expreval.cpp
r93174 r93178 563 563 564 564 /** 565 * Finds the end of the current variable expansion, taking nested expans oins565 * Finds the end of the current variable expansion, taking nested expansion 566 566 * into account. 567 567 * … … 575 575 * @param pfNested Where to return whether it's a nested (@c true) or plain 576 576 * one. 577 * 578 * @note This code would be somewhat simpler if we only used one style of 579 * wrappers (either parentheses or curly brackets). 580 */ 581 DECL_NO_INLINE(static, EXPRRET) expr_expand_find_end(PEXPR pThis, const char *pchSrc, size_t cchSrc, 582 size_t *pcchVarRef, bool *pfNested) 577 */ 578 static EXPRRET expr_expand_find_end(PEXPR pThis, const char *pchSrc, size_t cchSrc, size_t *pcchVarRef, bool *pfNested) 583 579 { 584 580 const char * const pchStart = pchSrc; 585 char achPars[EXPR_MAX_VAR_RECURSION];586 581 587 582 /* … … 590 585 Assert(cchSrc >= 2); 591 586 Assert(pchSrc[0] == '$'); 592 Assert(pchSrc[1] == '(' || pchSrc[1] == '}'); 593 unsigned cPars = 1; 594 char chEndPar = pchSrc[1] == '(' ? ')' : '}'; 595 achPars[0] = chEndPar; 587 Assert(pchSrc[1] == '{'); 588 unsigned cPars = 1; 596 589 pchSrc += 2; 597 590 cchSrc -= 2; … … 603 596 while (cchSrc > 0) 604 597 { 605 char ch2;606 598 char const ch = *pchSrc; 607 599 if ( ch == '$' 608 600 && cchSrc >= 2 609 && ( (ch2 = pchSrc[1]) == '(' 610 || ch2 == '{')) 611 { 612 if (cPars < RT_ELEMENTS(achPars)) 613 achPars[cPars++] = chEndPar = ch2 == '(' ? ')' : '}'; 601 && pchSrc[1] == '{') 602 { 603 if (cPars < EXPR_MAX_VAR_RECURSION) 604 cPars++; 614 605 else 615 606 { … … 625 616 pchSrc += 1; 626 617 cchSrc -= 1; 627 if (ch == chEndPar) 628 { 618 if (ch == '}') 629 619 if (--cPars == 0) 630 620 { … … 632 622 return kExprRet_Ok; 633 623 } 634 chEndPar = achPars[cPars];635 }636 Assert(chEndPar != '\0');637 624 } 638 625 } … … 651 638 * @param cchSrc The length of the string to expand. 652 639 * @param cDepth The recursion depth, starting at zero. 653 *654 * @note This code would be somewhat simpler if we only used one style of655 * wrappers (either parentheses or curly brackets).656 640 */ 657 641 static char *expr_expand_string(PEXPR pThis, const char *pchSrc, size_t cchSrc, unsigned cDepth) … … 675 659 if (pchDollar) 676 660 { 677 /* Treat lone $ w/o a following ( or{ as plain text. */661 /* Treat lone $ w/o a following { as plain text. */ 678 662 if ( cchPlain + 1 >= cchSrc 679 663 && pchDollar[0] == '$' 680 664 && ( cchPlain + 1 == cchSrc 681 || (pchDollar[1] != '{' && pchDollar[1] != '(')) )665 || pchDollar[1] != '{') ) 682 666 { 683 667 cchPlain += 1; … … 723 707 break; 724 708 725 /* If we don't have ${ or $( loop, just loop. */709 /* If we don't have ${, just loop. */ 726 710 if ( cchSrc < 2 727 711 || pchSrc[0] != '$' 728 || (pchSrc[1] != '{' && pchSrc[1] != '('))712 || pchSrc[1] != '{') 729 713 continue; 730 714 } … … 734 718 * finding the end of it and recursively dealing with any sub-expansions first. 735 719 */ 736 Assert(pchSrc[0] == '$' && (pchSrc[1] == '{' || pchSrc[1] == '('));720 Assert(pchSrc[0] == '$' && pchSrc[1] == '{'); 737 721 size_t cchVarRef; 738 722 bool fNested; … … 2379 2363 else 2380 2364 { 2381 char achPars[EXPR_MAX_VAR_RECURSION]; 2382 int iPar = -1; 2383 char chEndPar = '\0'; 2384 2365 unsigned cPars = 0; 2385 2366 pszStart = psz; 2386 2367 while ((ch = *psz) != '\0') 2387 2368 { 2388 char ch2; 2389 2390 /* $(adsf) or ${asdf} needs special handling. */ 2391 if ( ch == '$' 2392 && ( (ch2 = psz[1]) == '(' 2393 || ch2 == '{')) 2369 /* ${asdf} needs special handling. */ 2370 if ( ch == '$' 2371 && psz[1] == '{') 2394 2372 { 2395 2373 psz++; 2396 if (iPar > (int)(sizeof(achPars) / sizeof(achPars[0]))) 2374 if (cPars < EXPR_MAX_VAR_RECURSION) 2375 ++cPars; 2376 else 2397 2377 { 2398 2378 rc = expr_error(pThis, "Too deep nesting of variable expansions"); 2399 2379 break; 2400 2380 } 2401 achPars[++iPar] = chEndPar = ch2 == '(' ? ')' : '}';2402 2381 } 2403 else if (ch == chEndPar)2382 else if (ch == '}') 2404 2383 { 2405 i Par--;2406 chEndPar = iPar >= 0 ? achPars[iPar] : '\0';2384 if (cPars > 0) 2385 cPars--; 2407 2386 } 2408 else if ( !chEndPar)2387 else if (cPars == 0) 2409 2388 { 2410 2389 uchVal = expr_map_get(ch); -
trunk/src/VBox/Runtime/testcase/tstRTExprEval.cpp
r93175 r93178 133 133 CHECK_iResult(INT64_MAX); 134 134 g_fQueryVariableExpected = true; 135 RTTESTI_CHECK_RC(RTExprEvalToInteger(hExprEval, RT_STR_TUPLE("$ (MYVAR1)+ 0"), &iResult, NULL), VINF_SUCCESS);135 RTTESTI_CHECK_RC(RTExprEvalToInteger(hExprEval, RT_STR_TUPLE("${MYVAR1} + 0"), &iResult, NULL), VINF_SUCCESS); 136 136 CHECK_iResult(42); 137 RTTESTI_CHECK_RC(RTExprEvalToInteger(hExprEval, RT_STR_TUPLE("$ ($(MYNESTED1))+ 2"), &iResult, NULL), VINF_SUCCESS);137 RTTESTI_CHECK_RC(RTExprEvalToInteger(hExprEval, RT_STR_TUPLE("${${MYNESTED1}} + 2"), &iResult, NULL), VINF_SUCCESS); 138 138 CHECK_iResult(44); 139 139 g_fQueryVariableExpected = false; … … 173 173 } 174 174 175
Note:
See TracChangeset
for help on using the changeset viewer.