1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +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

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))