mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Don't allow 'enum' and 'typeset -T' to override special built-ins
Special builtins are undeleteable for a reason. But 'enum' and 'typeset -T' allow overriding them, causing an inconsistent state. @JohnoKing writes: | The behavior is rather buggy, as it appears to successfully | override normal builtins but fails to delete the special | builtins, leading to scenarios where both the original builtin | and type are run: | | $ typeset -T eval=(typeset BAD; typeset TYPE) # This should have failed | $ eval foo=BAD | /usr/bin/ksh: eval: line 1: foo: not found | $ enum trap=(BAD TYPE) # This also should have failed | $ trap foo=BAD | /usr/bin/ksh: trap: condition(s) required | $ enum umask=(BAD TYPE) | $ umask foo=BAD | $ echo $foo | BAD | | # Examples of general bugginess | $ trap bar=TYPE | /usr/bin/ksh: trap: condition(s) required | $ echo $bar | TYPE | $ eval var=TYPE | /usr/bin/ksh: eval: line 1: var: not found | $ echo $var | TYPE This commit fixes the following: The 'enum' and 'typeset -T' commands are no longer allowed to override and replace special built-in commands, except for type definition commands previously created by these commands; these are already (dis)allowed elsewhere. A command like 'typeset -T foo_t' without any assignments no longer creates an incompletely defined 'foo_t' built-in comamnd. Instead, it is now silently ignored for backwards compatibility. This did have a regression test checking for it, but I'm changing it because that's just not a valid use case. An incomplete type definition command does nothing useful and only crashes the shell when run. src/cmd/ksh93/bltins/enum.c: b_enum(): - Do not allow overriding non-type special built-ins. src/cmd/ksh93/sh/name.c: nv_setlist(): - Do not allow 'typeset -T' to override non-type special built-ins. To avoid an inconsistent state, this must be checked for while processing the assignments list before typeset is really invoked. src/cmd/ksh93/bltins_typeset.c: b_typeset(): - Only create a type command if sh.envlist is set, i.e., if some shell assignment(s) were passed to the 'typeset -T' command. Progresses: https://github.com/ksh93/ksh/issues/350
This commit is contained in:
parent
a36b96f9a4
commit
e6d0187dd8
8 changed files with 50 additions and 4 deletions
11
NEWS
11
NEWS
|
@ -3,6 +3,17 @@ For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0
|
||||||
|
|
||||||
Any uppercase BUG_* names are modernish shell bug IDs.
|
Any uppercase BUG_* names are modernish shell bug IDs.
|
||||||
|
|
||||||
|
2022-02-08:
|
||||||
|
|
||||||
|
- To avoid an inconsistent state, the 'enum' and 'typeset -T' commands are
|
||||||
|
no longer allowed to replace special built-in commands. For instance,
|
||||||
|
'enum trap=(a b c)' is now an error because 'trap' is a special built-in.
|
||||||
|
The ability of 'typeset -T' to redefine a type is not affected.
|
||||||
|
|
||||||
|
- A command like 'typeset -T foo_t' without any assignment no longer creates
|
||||||
|
an incompletely defined 'foo_t' built-in comamnd that will crash the shell
|
||||||
|
when used. Instead, it is now silently ignored for backwards compatibility.
|
||||||
|
|
||||||
2022-02-05:
|
2022-02-05:
|
||||||
|
|
||||||
- Fixed: for indexed arrays, given an unset array member a[i] with i > 0,
|
- Fixed: for indexed arrays, given an unset array member a[i] with i > 0,
|
||||||
|
|
|
@ -168,6 +168,10 @@ For more details, see the NEWS file and for complete details, see the git log.
|
||||||
return value that fits in a signed integer, typically a 32-bit value.
|
return value that fits in a signed integer, typically a 32-bit value.
|
||||||
Note that $? is truncated to 8 bits when the current (sub)shell exits.
|
Note that $? is truncated to 8 bits when the current (sub)shell exits.
|
||||||
|
|
||||||
|
31. The 'enum' and 'typeset -T' commands are no longer allowed to
|
||||||
|
override and replace special built-in commands, except for type
|
||||||
|
definition commands previously created by these commands.
|
||||||
|
|
||||||
____________________________________________________________________________
|
____________________________________________________________________________
|
||||||
|
|
||||||
KSH-93 VS. KSH-88
|
KSH-93 VS. KSH-88
|
||||||
|
|
|
@ -88,6 +88,8 @@ static const char enum_type[] =
|
||||||
"[+SEE ALSO?\benum\b(1), \btypeset\b(1)]"
|
"[+SEE ALSO?\benum\b(1), \btypeset\b(1)]"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
extern const char is_spcbuiltin[];
|
||||||
|
|
||||||
struct Enum
|
struct Enum
|
||||||
{
|
{
|
||||||
Namfun_t hdr;
|
Namfun_t hdr;
|
||||||
|
@ -243,6 +245,13 @@ int b_enum(int argc, char** argv, Shbltin_t *context)
|
||||||
#endif
|
#endif
|
||||||
while(cp = *argv++)
|
while(cp = *argv++)
|
||||||
{
|
{
|
||||||
|
/* Do not allow 'enum' to override special built-ins -- however, exclude
|
||||||
|
* previously created type commands from this search as that is handled elsewhere. */
|
||||||
|
if((tp=nv_search(cp,sh.bltin_tree,0)) && nv_isattr(tp,BLT_SPC) && !nv_search(cp,sh.typedict,0))
|
||||||
|
{
|
||||||
|
errormsg(SH_DICT,ERROR_exit(1),"%s:%s",cp,is_spcbuiltin);
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
if(!(np = nv_open(cp, (void*)0, NV_VARNAME|NV_NOADD)) || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem&(((1L<<ARRAY_BITS)-1))) < 2)
|
if(!(np = nv_open(cp, (void*)0, NV_VARNAME|NV_NOADD)) || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem&(((1L<<ARRAY_BITS)-1))) < 2)
|
||||||
{
|
{
|
||||||
error(ERROR_exit(1), "%s must name an array containing at least two elements",cp);
|
error(ERROR_exit(1), "%s must name an array containing at least two elements",cp);
|
||||||
|
|
|
@ -536,7 +536,7 @@ endargs:
|
||||||
errormsg(SH_DICT,ERROR_exit(1),"%s: unknown type",tdata.prefix);
|
errormsg(SH_DICT,ERROR_exit(1),"%s: unknown type",tdata.prefix);
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
else if(nv_isnull(tdata.tp))
|
else if(nv_isnull(tdata.tp) && sh.envlist) /* only create a type command if there were assignment(s) */
|
||||||
nv_newtype(tdata.tp);
|
nv_newtype(tdata.tp);
|
||||||
tdata.tp->nvenv = tdata.help;
|
tdata.tp->nvenv = tdata.help;
|
||||||
flag &= ~NV_TYPE;
|
flag &= ~NV_TYPE;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
|
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
|
||||||
#define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */
|
#define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */
|
||||||
#define SH_RELEASE_DATE "2022-02-05" /* must be in this format for $((.sh.version)) */
|
#define SH_RELEASE_DATE "2022-02-08" /* must be in this format for $((.sh.version)) */
|
||||||
#define SH_RELEASE_CPYR "(c) 2020-2022 Contributors to ksh " SH_RELEASE_FORK
|
#define SH_RELEASE_CPYR "(c) 2020-2022 Contributors to ksh " SH_RELEASE_FORK
|
||||||
|
|
||||||
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
|
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
|
||||||
|
|
|
@ -319,6 +319,13 @@ void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
|
||||||
cp = sh_mactrim(fp->fornam,-1);
|
cp = sh_mactrim(fp->fornam,-1);
|
||||||
else
|
else
|
||||||
cp = fp->fornam;
|
cp = fp->fornam;
|
||||||
|
/* Do not allow 'typeset -T' to override special built-ins -- however, exclude
|
||||||
|
* previously created type commands from this search as that is handled elsewhere. */
|
||||||
|
if(maketype && (np=nv_search(cp,sh.bltin_tree,0)) && nv_isattr(np,BLT_SPC) && !nv_search(cp,sh.typedict,0))
|
||||||
|
{
|
||||||
|
errormsg(SH_DICT,ERROR_exit(1),"%s:%s",cp,is_spcbuiltin);
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
error_info.line = fp->fortyp-sh.st.firstline;
|
error_info.line = fp->fortyp-sh.st.firstline;
|
||||||
if(!array && tp->tre.tretyp!=TLST && tp->com.comset && !tp->com.comarg && tp->com.comset->argval[0]==0 && tp->com.comset->argval[1]=='[')
|
if(!array && tp->tre.tretyp!=TLST && tp->com.comset && !tp->com.comarg && tp->com.comset->argval[0]==0 && tp->com.comset->argval[1]=='[')
|
||||||
array |= (tp->com.comset->argflag&ARG_MESSAGE)?NV_IARRAY:NV_ARRAY;
|
array |= (tp->com.comset->argflag&ARG_MESSAGE)?NV_IARRAY:NV_ARRAY;
|
||||||
|
|
|
@ -161,5 +161,12 @@ then enum PARSER2_t=(a b)
|
||||||
fi
|
fi
|
||||||
PATH=/dev/null command -v PARSER2_t >/dev/null && err_exit "PARSER2_t incompletely defined though definition was never executed"
|
PATH=/dev/null command -v PARSER2_t >/dev/null && err_exit "PARSER2_t incompletely defined though definition was never executed"
|
||||||
|
|
||||||
|
# ======
|
||||||
|
# https://github.com/ksh93/ksh/issues/350#issuecomment-982168684
|
||||||
|
got=$("$SHELL" -c 'enum trap=(BAD TYPE)' 2>&1)
|
||||||
|
exp=': trap: is a special shell builtin'
|
||||||
|
[[ $got == *"$exp" ]] || err_exit "enum overrides special builtin" \
|
||||||
|
"(expected match of *$(printf %q "$exp"); got $(printf %q "$got"))"
|
||||||
|
|
||||||
# ======
|
# ======
|
||||||
exit $((Errors<125?Errors:125))
|
exit $((Errors<125?Errors:125))
|
||||||
|
|
|
@ -565,8 +565,9 @@ unset z
|
||||||
u_t -a x | read z
|
u_t -a x | read z
|
||||||
[[ $z == unset ]] && err_exit 'unset discipline called on type creation'
|
[[ $z == unset ]] && err_exit 'unset discipline called on type creation'
|
||||||
|
|
||||||
{ z=$($SHELL 2> /dev/null 'typeset -T foo; typeset -T') ;} 2> /dev/null
|
got=$("$SHELL" -c 'typeset -T foo; typeset -T' 2>&1)
|
||||||
[[ $z == 'typeset -T foo' ]] || err_exit '"typeset -T foo; typeset -T" failed'
|
[[ -z $got ]] || err_exit '"typeset -T foo; typeset -T" exposed incomplete type builtin' \
|
||||||
|
"(got $(printf %q "$got"))"
|
||||||
|
|
||||||
{ z=$($SHELL 2> /dev/null 'typeset -T foo=bar; typeset -T') ;} 2> /dev/null
|
{ z=$($SHELL 2> /dev/null 'typeset -T foo=bar; typeset -T') ;} 2> /dev/null
|
||||||
[[ $z ]] && err_exit '"typeset -T foo=bar" should not creates type foo'
|
[[ $z ]] && err_exit '"typeset -T foo=bar" should not creates type foo'
|
||||||
|
@ -657,5 +658,12 @@ exp='Subsh_t -a v=((typeset -i x=1) (typeset -i x=2) (typeset -i x=3))'
|
||||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||||
PATH=/dev/null command -v Subsh_t >/dev/null && err_exit "Subsh_t leaked out of subshell"
|
PATH=/dev/null command -v Subsh_t >/dev/null && err_exit "Subsh_t leaked out of subshell"
|
||||||
|
|
||||||
|
# ======
|
||||||
|
# https://github.com/ksh93/ksh/issues/350#issuecomment-982168684
|
||||||
|
got=$("$SHELL" -c 'typeset -T trap=( typeset -i i )' 2>&1)
|
||||||
|
exp=': trap: is a special shell builtin'
|
||||||
|
[[ $got == *"$exp" ]] || err_exit "typeset -T overrides special builtin" \
|
||||||
|
"(expected match of *$(printf %q "$exp"); got $(printf %q "$got"))"
|
||||||
|
|
||||||
# ======
|
# ======
|
||||||
exit $((Errors<125?Errors:125))
|
exit $((Errors<125?Errors:125))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue