1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-06-01 12:56:04 +02:00

21862/21863: GLOB_SUBST shouldn't swallow up backslashes in parameter

substitutions that don't match anything.
This commit is contained in:
Peter Stephenson 2005-10-11 16:48:05 +00:00
parent 1eaa7fee0d
commit cca66ab341
8 changed files with 92 additions and 21 deletions

View File

@ -1,3 +1,10 @@
2005-10-11 Peter Stephenson <pws@csr.com>
* 21862/21863: Src/glob.c, Src/lex.c, Src/pattern.c, Src/subst.c,
Src/zsh.h, Test/D04parameter.ztst, Test/ztst.zsh: Ensure that
backslashes in parameters substituted by GLOB_SUBST are not
swallowed up if there is no pattern match.
2005-10-07 Peter Stephenson <pws@csr.com>
* Stephen Rüger: 21846: Completion/Unix/Command/_chmod: too

View File

@ -2487,19 +2487,29 @@ igetmatch(char **sp, Patprog p, int fl, int n, char *replstr)
mod_export void
tokenize(char *s)
{
zshtokenize(s, 0);
zshtokenize(s, 0, 0);
}
/*
* shtokenize is used when we tokenize a string with GLOB_SUBST set.
* In that case we need to retain backslashes when we turn the
* pattern back into a string, so that the string is not
* modified if it failed to match a pattern.
*
* It may be modified by the effect of SH_GLOB which turns off
* various zsh-specific options.
*/
/**/
mod_export void
shtokenize(char *s)
{
zshtokenize(s, isset(SHGLOB));
zshtokenize(s, 1, isset(SHGLOB));
}
/**/
static void
zshtokenize(char *s, int shglob)
zshtokenize(char *s, int glbsbst, int shglob)
{
char *t;
int bslash = 0;
@ -2508,9 +2518,10 @@ zshtokenize(char *s, int shglob)
cont:
switch (*s) {
case Bnull:
case Bnullkeep:
case '\\':
if (bslash) {
s[-1] = Bnull;
s[-1] = glbsbst ? Bnullkeep : Bnull;
break;
}
bslash = 1;
@ -2519,7 +2530,7 @@ zshtokenize(char *s, int shglob)
if (shglob)
break;
if (bslash) {
s[-1] = Bnull;
s[-1] = glbsbst ? Bnullkeep : Bnull;
break;
}
t = s;
@ -2549,7 +2560,7 @@ zshtokenize(char *s, int shglob)
for (t = ztokens; *t; t++)
if (*t == *s) {
if (bslash)
s[-1] = Bnull;
s[-1] = glbsbst ? Bnullkeep : Bnull;
else
*s = (t - ztokens) + Pound;
break;
@ -2569,12 +2580,23 @@ remnulargs(char *s)
char *o = s, c;
while ((c = *s++))
if (INULL(c)) {
if (c == Bnullkeep) {
/*
* An active backslash that needs to be turned back into
* a real backslash for output. However, we don't
* do that yet since we need to ignore it during
* pattern matching.
*/
continue;
} else if (INULL(c)) {
char *t = s - 1;
while ((c = *s++))
if (!INULL(c))
while ((c = *s++)) {
if (c == Bnullkeep)
*t++ = '\\';
else if (!INULL(c))
*t++ = c;
}
*t = '\0';
if (!*o) {
o[0] = Nularg;

View File

@ -33,7 +33,7 @@
/* tokens */
/**/
mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\";
mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\\\";
/* parts of the current token */

View File

@ -260,13 +260,13 @@ static char endseg[] = {
static char endstr[] = {
'/', /* file only */
'\0', Bar, Outpar, Quest, Star, Inbrack, Inpar, Inang,
'\0', Bar, Outpar, Quest, Star, Inbrack, Inpar, Inang, Bnullkeep,
/* all patterns */
Tilde, Hat, Pound /* extended glob only */
};
#define PATENDSTRLEN_NORM 9
#define PATENDSTRLEN_EXT 12
#define PATENDSTRLEN_NORM 10
#define PATENDSTRLEN_EXT 13
/* Default size for pattern buffer */
@ -1240,6 +1240,13 @@ patcomppiece(int *flagp)
*/
return 0;
break;
case Bnullkeep:
/*
* Marker for restoring a backslash in output:
* does not match a character.
*/
return patcomppiece(flagp);
break;
#ifdef DEBUG
default:
dputs("BUG: character not handled in patcomppiece");

View File

@ -1945,7 +1945,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
*/
for (ptr = s; (c = *ptr) && c != '/'; ptr++)
{
if ((c == Bnull || c == '\\') && ptr[1])
if ((c == Bnull || c == Bnullkeep || c == '\\') && ptr[1])
{
if (ptr[1] == '/')
chuck(ptr);
@ -2846,11 +2846,11 @@ modify(char **str, char **ptr)
}
zsfree(hsubr);
for (tt = hsubl; *tt; tt++)
if (INULL(*tt))
if (INULL(*tt) && *tt != Bnullkeep)
chuck(tt--);
untokenize(hsubl);
for (tt = hsubr = ztrdup(ptr2); *tt; tt++)
if (INULL(*tt))
if (INULL(*tt) && *tt != Bnullkeep)
chuck(tt--);
ptr2[-1] = del;
if (sav)

View File

@ -120,7 +120,10 @@ struct mathfunc {
#define DEFAULT_IFS " \t\n\203 "
/* Character tokens */
/*
* Character tokens.
* These should match the characters in ztokens, defined in lex.c
*/
#define Pound ((char) 0x84)
#define String ((char) 0x85)
#define Hat ((char) 0x86)
@ -141,15 +144,33 @@ struct mathfunc {
#define Tilde ((char) 0x95)
#define Qtick ((char) 0x96)
#define Comma ((char) 0x97)
/*
* Null arguments: placeholders for single and double quotes
* and backslashes.
*/
#define Snull ((char) 0x98)
#define Dnull ((char) 0x99)
#define Bnull ((char) 0x9a)
#define Nularg ((char) 0x9b)
/*
* Backslash which will be returned to "\" instead of being stripped
* when we turn the string into a printable format.
*/
#define Bnullkeep ((char) 0x9b)
/*
* Null argument that does not correspond to any character.
* This should be last as it does not appear in ztokens and
* is used to initialise the IMETA type in inittyptab().
*/
#define Nularg ((char) 0x9c)
#define INULL(x) (((x) & 0xfc) == 0x98)
#define INULL(x) (((x) & 0xf8) == 0x98)
/*
* Take care to update the use of IMETA appropriately when adding
* tokens here.
*/
/* Marker used in paramsubst for rc_expand_param */
#define Marker ((char) 0x9c)
#define Marker ((char) 0xa0)
/* chars that need to be quoted if meant literally */

View File

@ -196,6 +196,20 @@
>* boringfile evenmoreboringfile boringfile evenmoreboringfile
>boringfile evenmoreboringfile
# The following tests a bug where globsubst didn't preserve
# backslashes when printing out the original string.
str1='\\*\\'
(
setopt globsubst nonomatch
[[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1
[[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1
[[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1
)
0:globsubst with backslashes
>\\ matched by \\*\\
>\\foo matched by \\*\\
>a\\b not matched by \\*\\
print -l "${$(print one word)}" "${=$(print two words)}"
0:splitting of $(...) inside ${...}
>one word

View File

@ -280,7 +280,7 @@ ZTST_diff() {
diff_out=$(diff "$@")
diff_ret="$?"
if [[ "$diff_ret" != "0" ]]; then
echo "$diff_out"
print -r "$diff_out"
fi
return "$diff_ret"