From: Eric Pouech epouech@codeweavers.com
Also fix returned string in case of incorrect range for substring.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57809
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/tests/test_builtins.cmd.exp | 14 +++---- programs/cmd/wcmdmain.c | 48 +++++++++++------------- 2 files changed, 28 insertions(+), 34 deletions(-)
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 63487a098a5..5b0a93bd22d 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -778,16 +778,16 @@ e@or_broken@qwerty r@or_broken@qwerty ty 'y' -@todo_wine@'' -@todo_wine@'' +'' +'' 'qwerty' '' 'qw' -@todo_wine@'WINE_VAR:~2a' -@todo_wine@'WINE_VAR:~2a,2' -@todo_wine@'WINE_VAR:~a,2' -@todo_wine@'WINE_VAR:~2,2a' -@todo_wine@'WINE_VAR:~-' +'WINE_VAR:~2a' +'WINE_VAR:~2a,2' +'WINE_VAR:~a,2' +'WINE_VAR:~2,2a' +'WINE_VAR:~-' ------------ Testing variable partial replacement ------------ azertyazERTY ertyERTY diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 48589a2245d..9c7377e3258 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -514,6 +514,13 @@ WCHAR *WCMD_strip_quotes(WCHAR *cmd) { return lastquote; }
+static inline int read_int_in_range(const WCHAR *from, WCHAR **after, int low, int high) +{ + int val = wcstol(from, after, 10); + val += (val < 0) ? high : low; + return val <= low ? low : (val >= high ? high : val); +} + /************************************************************************* * WCMD_expand_envvar * @@ -598,34 +605,21 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start) */
/* ~ is substring manipulation */ - if (colonpos[1] == L'~') { - - int substrposition, substrlength = 0; - WCHAR *commapos = wcschr(colonpos+2, L','); - WCHAR *startCopy; - - substrposition = wcstol(colonpos+2, NULL, 10); - if (commapos) substrlength = wcstol(commapos+1, NULL, 10); - - /* Check bounds */ - if (substrposition >= 0) { - startCopy = &thisVarContents[min(substrposition, len - 1)]; - } else { - startCopy = &thisVarContents[max(0, len + substrposition)]; - } - - if (commapos == NULL) - /* Copy the lot */ - return WCMD_strsubstW(start, endOfVar + 1, startCopy, -1); - if (substrlength < 0) { + if (colonpos[1] == L'~') + { + int substr_beg, substr_end; + WCHAR *ptr;
- int copybytes = len + substrlength - (startCopy - thisVarContents); - if (copybytes >= len) copybytes = len - 1; - else if (copybytes < 0) copybytes = 0; - return WCMD_strsubstW(start, endOfVar + 1, startCopy, copybytes); - } - substrlength = min(substrlength, len - (startCopy - thisVarContents)); - return WCMD_strsubstW(start, endOfVar + 1, startCopy, substrlength); + substr_beg = read_int_in_range(colonpos + 2, &ptr, 0, len); + if (*ptr == L',') + substr_end = read_int_in_range(ptr + 1, &ptr, substr_beg, len); + else + substr_end = len; + if (*ptr == L'\0') + return WCMD_strsubstW(start, endOfVar + 1, &thisVarContents[substr_beg], substr_end - substr_beg); + /* error, remove enclosing % pair (in place) */ + memmove(start, start + 1, (endOfVar - start - 1) * sizeof(WCHAR)); + return WCMD_strsubstW(endOfVar - 1, endOfVar + 1, NULL, 0); /* search and replace manipulation */ } else { WCHAR *equalspos = wcschr(colonpos, L'=');