1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 03:32:24 +00:00

Correctly block invalid values for arrays of an enum type

This fixes part of https://github.com/ksh93/ksh/issues/87:

Scalar arrays (-a) and associative arrays (-A) of a type created by
'enum' did not consistently block values not specified by the enum
type, yielding corrupted results.

An expansion of type "${array[@]}" yielded random numbers instead
of values for associative arrays of a type created by 'enum'.

This does not yet fix another problem: ${array[@]} does not yield
all values for associative enum arrays.

src/cmd/ksh93/bltins/enum.c: put_enum():
- Always throw an error if the value is not in the list of possible
  values for an enum type. Remove incorrect check for the NV_NOFREE
  flag. Whatever that was meant to accomplish, I've no idea.

src/cmd/ksh93/sh/array.c: nv_arraysettype():
- Instead of sh_eval()ing a shell assignment, use nv_putval()
  directly. Also use the stack (see src/lib/libast/man/stk.3)
  instead of malloc to save the value; it's faster and will be
  auto-freed at some point. This shortens the function and makes it
  faster by not entering into a whole new shell context -- which
  also fixes another problem: the error message from put_enum()
  didn't cause the shell to exit for indexed enum arrays.

src/cmd/ksh93/sh/name.c: nv_setlist():
- Apply a patch from David Korn that correctly sets the data type
  for associative arrays, fixing the ${array[@]} expansion yielding
  random numbers. Thanks to @JohnoKing for the pointer.
  https://github.com/ksh93/ksh/issues/87#issuecomment-662613887
  https://www.mail-archive.com/ast-developers@lists.research.att.com/msg00697.html

src/cmd/ksh93/tests/enum.sh:
- Add tests checking that invalid values are correctly blocked for
  indexed and associative arrays of an enum type.

Makes progress on: https://github.com/ksh93/ksh/issues/87
This commit is contained in:
Martijn Dekker 2021-02-01 16:19:04 +00:00
parent 6a0e9a1a75
commit 5491fe9724
6 changed files with 30 additions and 23 deletions

10
NEWS
View file

@ -3,6 +3,14 @@ For full details, see the git log at: https://github.com/ksh93/ksh
Any uppercase BUG_* names are modernish shell bug IDs.
2021-02-01:
- Fixed: scalar arrays (-a) and associative arrays (-A) of a type created by
'enum' allowed values not specified by the enum type, corrupting results.
- Fixed: the "${array[@]}" expansion for associative arrays of a type created
by 'enum' expanded to random numbers instead of the array's values.
2021-01-30:
- The -x option to the 'command' built-in now causes it to bypass built-ins
@ -12,7 +20,7 @@ Any uppercase BUG_* names are modernish shell bug IDs.
a command with many arguments was divided into several command invocations.
- The 2020-08-16 fix is improved with a compile-time feature test that
detects if and how the OS uses data alignment in the arguments list,
detects if the OS requires extra bytes per argument in the arguments list,
maximising the efficiency of 'command -x' for the system it runs on.
2021-01-24:

View file

@ -150,8 +150,7 @@ static void put_enum(Namval_t* np,const char *val,int flags,Namfun_t *fp)
}
i++;
}
if(nv_isattr(np,NV_NOFREE))
error(ERROR_exit(1), "%s: invalid value %s",nv_name(np),val);
error(ERROR_exit(1), "%s: invalid value %s",nv_name(np),val);
}
static char* get_enum(register Namval_t* np, Namfun_t *fp)

View file

@ -20,7 +20,7 @@
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
#define SH_RELEASE_SVER "1.0.0-alpha" /* semantic version number: https://semver.org */
#define SH_RELEASE_DATE "2021-01-31" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_DATE "2021-02-01" /* must be in this format for $((.sh.version)) */
#define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */

View file

@ -407,11 +407,7 @@ static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags)
{
Namval_t *nq;
char *av[2];
int rdonly = nv_isattr(np,NV_RDONLY);
int xtrace = sh_isoption(SH_XTRACE);
Namarr_t *ap = nv_arrayptr(np);
av[1] = 0;
sh.last_table = 0;
if(!ap->table)
{
@ -420,30 +416,20 @@ int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags)
}
if(nq = nv_search(sub, ap->table, NV_ADD))
{
char *saved_value;
int rdonly = nv_isattr(np,NV_RDONLY);
if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0)
_nv_unset(nq,NV_RDONLY);
nv_arraychild(np,nq,0);
if(!nv_isattr(tp,NV_BINARY))
{
sfprintf(sh.strbuf,"%s=%s",nv_name(nq),nv_getval(np));
av[0] = strdup(sfstruse(sh.strbuf));
}
saved_value = stkcopy(stkstd,nv_getval(np));
if(!nv_clone(tp,nq,flags|NV_NOFREE))
return(0);
ap->nelem |= ARRAY_SCAN;
if(!rdonly)
nv_offattr(nq,NV_RDONLY);
if(!nv_isattr(tp,NV_BINARY))
{
if(xtrace)
sh_offoption(SH_XTRACE);
ap->nelem &= ~ARRAY_SCAN;
sh_eval(sh_sfeval(av),0);
ap->nelem |= ARRAY_SCAN;
free((void*)av[0]);
if(xtrace)
sh_onoption(SH_XTRACE);
}
nv_putval(nq,saved_value,0);
ap->nelem |= ARRAY_SCAN;
return(1);
}
return(0);

View file

@ -389,6 +389,8 @@ void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
if(array&NV_ARRAY)
{
nv_setarray(np,nv_associative);
if(typ)
nv_settype(np,typ,0);
}
else
{

View file

@ -74,4 +74,16 @@ arr[green]=foo
read -A arr <<< 'x y z xx yy'
[[ ${arr[1]} == ${arr[green]} ]] || err_exit 'arr[1] != arr[green] after read'
# enum arrays didn't block unspecified values
# https://github.com/ksh93/ksh/issues/87
exp=': Color_t: clr[2]: invalid value WRONG'
got=$(set +x; redirect 2>&1; Color_t -a clr=(red blue WRONG yellow); printf '%s\n' "${clr[@]}")
(((e = $?) == 1)) && [[ $got == *"$exp" ]] || err_exit "indexed enum array, unspecified value:" \
"expected status 1, *$(printf %q "$exp"); got status $e, $(printf %q "$got")"
exp=': clr: invalid value BAD'
got=$(set +x; redirect 2>&1; Color_t -A clr=([foo]=red [bar]=blue [bad]=BAD); printf '%s\n' "${clr[@]}")
(((e = $?) == 1)) && [[ $got == *"$exp" ]] || err_exit "associative enum array, unspecified value:" \
"expected status 1, *$(printf %q "$exp"); got status $e, $(printf %q "$got")"
# ======
exit $((Errors<125?Errors:125))