mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-11-24 14:01:03 +01:00
54064: avoid crash on named references to argv/ARGC, improve valid_nameref()
Leaves some edgecase issues unresolved (see tests).
This commit is contained in:
parent
45b6de088a
commit
8eec2c793c
3 changed files with 134 additions and 26 deletions
|
|
@ -1,3 +1,9 @@
|
|||
2025-11-10 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 54064: Src/params.c, Test/K01nameref.ztst: avoid crash on named
|
||||
references to argv/ARGC, improve syntax checks in valid_nameref().
|
||||
Leaves some edgecase issues unresolved (see tests).
|
||||
|
||||
2025-11-10 Oliver Kiddle <opk@zsh.org>
|
||||
|
||||
* 53402, 54042: Src/Zle/termquery.c, Src/Zle/zle_main.c,
|
||||
|
|
|
|||
67
Src/params.c
67
Src/params.c
|
|
@ -1309,7 +1309,6 @@ isident(char *s)
|
|||
/* Require balanced [ ] pairs with something between */
|
||||
if (!(ss = parse_subscript(++ss, 1, ']')))
|
||||
return 0;
|
||||
untokenize(s);
|
||||
return !ss[1];
|
||||
}
|
||||
|
||||
|
|
@ -3247,8 +3246,8 @@ assignsparam(char *s, char *val, int flags)
|
|||
return NULL;
|
||||
}
|
||||
if (*val && (v->pm->node.flags & PM_NAMEREF)) {
|
||||
if (!valid_refname(val)) {
|
||||
zerr("invalid variable name: %s", val);
|
||||
if (!valid_refname(val, v->pm->node.flags)) {
|
||||
zerr("invalid name reference: %s", val);
|
||||
zsfree(val);
|
||||
unqueue_signals();
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
|
|
@ -6505,30 +6504,48 @@ upscope_upper(Param pm, int reflevel)
|
|||
|
||||
/**/
|
||||
static int
|
||||
valid_refname(char *val)
|
||||
valid_refname(char *val, int flags)
|
||||
{
|
||||
char *t = itype_end(val, INAMESPC, 0);
|
||||
char *t;
|
||||
|
||||
if (idigit(*val))
|
||||
return 0;
|
||||
if (*t != 0) {
|
||||
if (*t == '[') {
|
||||
tokenize(t = dupstring(t+1));
|
||||
while ((t = parse_subscript(t, 0, ']')) && *t++ == Outbrack) {
|
||||
if (*t == Inbrack)
|
||||
++t;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (t && *t) {
|
||||
/* zwarn("%s: stuff after subscript: %s", val, t); */
|
||||
t = NULL;
|
||||
}
|
||||
} else if (t[1] || !(*t == '!' || *t == '?' ||
|
||||
*t == '$' || *t == '-' ||
|
||||
*t == '0' || *t == '_')) {
|
||||
/* Skipping * @ # because of doshfunc() implementation */
|
||||
t = NULL;
|
||||
if (flags & PM_UPPER) {
|
||||
/* Upward reference to positionals is doomed to fail */
|
||||
if (idigit(*val))
|
||||
return 0;
|
||||
t = itype_end(val, INAMESPC, 0);
|
||||
if ((t - val == 4) &&
|
||||
(!strncmp(val, "argv", 4) ||
|
||||
!strncmp(val, "ARGC", 4)))
|
||||
return 0;
|
||||
} else if (idigit(*val)) {
|
||||
t = val;
|
||||
while (*++t)
|
||||
if (!idigit(*t))
|
||||
break;
|
||||
if (*t && *t != '[') /* Need to test Inbrack here too? */
|
||||
return 0;
|
||||
} else
|
||||
t = itype_end(val, INAMESPC, 0);
|
||||
|
||||
if (t == val) {
|
||||
if (!(*t == '!' || *t == '?' ||
|
||||
*t == '$' || *t == '-' ||
|
||||
*t == '_'))
|
||||
return 0;
|
||||
++t;
|
||||
}
|
||||
if (*t == '[') {
|
||||
/* Another bit of isident() to emulate */
|
||||
tokenize(t = dupstring(t+1));
|
||||
while ((t = parse_subscript(t, 0, ']')) && *t++ == Outbrack) {
|
||||
if (*t == Inbrack)
|
||||
++t;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (t && *t) {
|
||||
/* zwarn("%s: stuff after subscript: %s", val, t); */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return !!t;
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ F:ksh93 does not implement this either
|
|||
unset -n ptr1
|
||||
typeset -n ptr1='not[2]good'
|
||||
1:invalid nameref
|
||||
*?*invalid variable name: not\[2\]good
|
||||
*?*invalid name reference: not\[2\]good
|
||||
|
||||
unset -n ptr1
|
||||
unset hash
|
||||
|
|
@ -1181,6 +1181,91 @@ F:previously this could create an infinite recursion and crash
|
|||
>h2: ref1=f1 ref2=f1 ref3=f1
|
||||
>f1: ref1=f1 ref2=f1 ref3=f1
|
||||
|
||||
#
|
||||
# The following two tests are linked, do not separate
|
||||
#
|
||||
|
||||
edgelocal() ( local -n x=$1; typeset -p x; print -r $x )
|
||||
edgeupper() ( local -nu x=$1; typeset -p x; print -r $x )
|
||||
for edge in argv ARGC \@ \* \# 0 1 01 \! \? - _
|
||||
do
|
||||
edgelocal $edge
|
||||
edgelocal "$edge""[1]"
|
||||
edgeupper $edge
|
||||
done
|
||||
0:references to builtin specials
|
||||
F:Subscripting on 1 01 ! ? - should print first character but do not
|
||||
>typeset -n x=argv
|
||||
>argv
|
||||
>typeset -n x='argv[1]'
|
||||
>argv[1]
|
||||
>typeset -n x=ARGC
|
||||
>1
|
||||
>typeset -n x='ARGC[1]'
|
||||
>1
|
||||
>typeset -n x=0
|
||||
>edgelocal
|
||||
>typeset -n x='0[1]'
|
||||
>e
|
||||
>typeset -n x=1
|
||||
>
|
||||
>typeset -n x='1[1]'
|
||||
>
|
||||
>typeset -n x=01
|
||||
>
|
||||
>typeset -n x='01[1]'
|
||||
>
|
||||
>typeset -n x=!
|
||||
>0
|
||||
>typeset -n x='![1]'
|
||||
>
|
||||
>typeset -un x=!
|
||||
>0
|
||||
>typeset -n x='?'
|
||||
>0
|
||||
>typeset -n x='?[1]'
|
||||
>
|
||||
>typeset -un x='?'
|
||||
>0
|
||||
>typeset -n x=-
|
||||
>569X
|
||||
>typeset -n x='-[1]'
|
||||
>
|
||||
>typeset -un x=-
|
||||
>569X
|
||||
>typeset -n x=_
|
||||
>x
|
||||
>typeset -n x='_[1]'
|
||||
>x
|
||||
>typeset -un x=_
|
||||
>x
|
||||
?edgeupper: invalid name reference: argv
|
||||
?edgeupper: invalid name reference: ARGC
|
||||
?edgelocal: invalid name reference: @
|
||||
?edgelocal: invalid name reference: @[1]
|
||||
?edgeupper: invalid name reference: @
|
||||
?edgelocal: invalid name reference: *
|
||||
?edgelocal: invalid name reference: *[1]
|
||||
?edgeupper: invalid name reference: *
|
||||
?edgelocal: invalid name reference: #
|
||||
?edgelocal: invalid name reference: #[1]
|
||||
?edgeupper: invalid name reference: #
|
||||
?edgeupper: invalid name reference: 0
|
||||
?edgeupper: invalid name reference: 1
|
||||
?edgeupper: invalid name reference: 01
|
||||
|
||||
edgelocal \$
|
||||
edgelocal '$[1]'
|
||||
edgeupper \$
|
||||
unfunction edgelocal edgeupper
|
||||
0qf:references to $$
|
||||
F:$$[1] reference should print the first digit of $$ but prints nothing
|
||||
>typeset -n x='$'
|
||||
>$$
|
||||
>typeset -n x='\$[1]'
|
||||
>$$[1]
|
||||
>$$
|
||||
|
||||
#
|
||||
# The following tests are run in interactive mode, using PS1 as an
|
||||
# assignable special with side-effects. This crashed at one time.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue