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:
parent
1eaa7fee0d
commit
cca66ab341
|
@ -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
|
||||
|
|
40
Src/glob.c
40
Src/glob.c
|
@ -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;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
/* tokens */
|
||||
|
||||
/**/
|
||||
mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\";
|
||||
mod_export char ztokens[] = "#$^*()$=|{}[]`<>?~`,'\"\\\\";
|
||||
|
||||
/* parts of the current token */
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
29
Src/zsh.h
29
Src/zsh.h
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue