Skip to content

Commit 3ca5470

Browse files
committed
Delete np->dynscope botch; refactor nvflags to uint32_t instead
This commit refactors the local builtin to take advantage of some changes I intend to submit later as separate pull requests. These are: - np->nvflags has been expanded from 16-bit to 32-bit. This fixes the longstanding limitation detailed in a previous ksh2020 bug: att#1038. The fix consists of masking out nv_open-centric flags with explicit uses of the new NV_OPENMASK, rather than implicitly and obtusely abusing the limitations of unsigned short types. Here, I take advantage of it for storing NV_DYNAMIC in np->nvflags and using it from there, which is a safer and more simple choice long term. - A bugfix from ksh93v- 2012-08-24 has been backported to fix a potential segfault that is triggered under ASan when changing the sizes of np->nvsize and np->nvflags to uint32_t. This cannot be triggered on the dev branch, but I will submit this individually soon enough. (I would have already submitted it had I not been forced to deal with a broken PSU shortly after submitting ksh93#805; 0 out of 10 experience don't recommend). - Updated comment regarding pitfalls in the ksh93v- and current implementation of local. In any case I intend to separate out various fixes from this branch and submit them as separate pull requests, if only to eventually reduce the scope of this one to just the local builtin and nothing else (the sh_funscope refactor for instance fixes an out of bounds bug that has been on the dev branch for far too long). Unfortunately my life has been quite hellish lately, so there is no ETA yet.
1 parent 1239454 commit 3ca5470

File tree

8 files changed

+33
-53
lines changed

8 files changed

+33
-53
lines changed

src/cmd/ksh93/include/name.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ struct Ufunction
8787

8888
/* The following attributes are for internal use */
8989
#define NV_NOCHANGE (NV_EXPORT|NV_MINIMAL|NV_RDONLY|NV_TAGGED|NV_NOFREE|NV_ARRAY)
90-
#define NV_ATTRIBUTES (~(NV_NOSCOPE|NV_ARRAY|NV_NOARRAY|NV_IDENT|NV_ASSIGN|NV_REF|NV_VARNAME|NV_STATIC))
90+
#define NV_ATTRIBUTES (NV_ARRAY|NV_IDENT|NV_ASSIGN|NV_REF)
91+
#define NV_OPENMASK (NV_APPEND|NV_MOVE|NV_NOARRAY|NV_IARRAY|NV_VARNAME|NV_NOADD|NV_NOSCOPE|NV_NOFAIL|NV_UNATTR|NV_GLOBAL|NV_TYPE|NV_STATIC|NV_COMVAR|NV_STATSCOPE)
9192
#define NV_PARAM NV_NODISC /* expansion use positional params */
9293

9394
/* This following are for use with nodes which are not name-values */

src/cmd/ksh93/include/nval.h

+3-15
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,8 @@ struct Namval
107107
{
108108
Dtlink_t nvlink; /* space for cdt links */
109109
char *nvname; /* pointer to name of the node */
110-
#if _ast_sizeof_pointer == 8
111-
# if _ast_intswap > 0
112-
unsigned short nvflag; /* attributes */
113-
unsigned short dynscope;
114-
# else
115-
unsigned short dynscope;
116-
unsigned short nvflag; /* attributes */
117-
# endif
110+
uint32_t nvflag; /* attributes */
118111
uint32_t nvsize; /* size or base */
119-
#else
120-
unsigned short nvflag; /* attributes */
121-
unsigned short nvsize; /* size or base */
122-
unsigned int dynscope;
123-
#endif
124112
Namfun_t *nvfun; /* pointer to trap functions */
125113
void *nvalue; /* pointer to any kind of value */
126114
void *nvmeta; /* pointer to any of various kinds of type-dependent data */
@@ -188,8 +176,8 @@ struct Namval
188176
#define NV_NODISC NV_IDENT /* ignore disciplines */
189177
#define NV_UNATTR 0x800000 /* unset attributes before assignment */
190178
#define NV_GLOBAL 0x20000000 /* create global variable, ignoring local scope */
191-
#define NV_DYNAMIC 0x40000000 /* create dynamically scoped variable */
192-
#define NV_STATSCOPE 0x80000000 /* force creation of statically scoped variable */
179+
#define NV_STATSCOPE 0x40000000 /* force creation of statically scoped variable */
180+
#define NV_DYNAMIC 0x80000000 /* create dynamically scoped variable */
193181

194182
#define NV_FUNCT NV_IDENT /* option for nv_create */
195183
#define NV_BLTINOPT NV_ZFILL /* mark builtins in libcmd */

src/cmd/ksh93/sh/arith.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl
231231
case ASSIGN:
232232
{
233233
Namval_t *np;
234-
unsigned short attr;
234+
uint32_t attr;
235235
if (lvalue->sub && lvalue->nosub > 0) /* indexed array ARITH_ASSIGNOP */
236236
{
237237
np = (Namval_t*)lvalue->sub; /* use saved subscript reference instead of last worked value */

src/cmd/ksh93/sh/name.c

+7-18
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ struct sh_type
7979
Namval_t *last_table;
8080
Namval_t *namespace;
8181
int flags;
82-
short size;
82+
int32_t size;
8383
short len;
8484
} entries[NVCACHE];
8585
short index;
@@ -443,13 +443,11 @@ void nv_setlist(struct argnod *arg,int flags, Namval_t *typ)
443443
nv_putsub(np, NULL, ARRAY_SCAN);
444444
if(!ap->fun && !(ap->nelem&ARRAY_TREE) && !np->nvfun->next && !nv_type(np))
445445
{
446-
unsigned short nvflag = np->nvflag;
446+
uint32_t nvflag = np->nvflag;
447447
uint32_t nvsize = np->nvsize;
448-
uint32_t nvdynscope = np->dynscope;
449448
_nv_unset(np,NV_EXPORT);
450449
np->nvflag = nvflag;
451450
np->nvsize = nvsize;
452-
np->dynscope = nvdynscope;
453451
}
454452
else
455453
{
@@ -563,7 +561,6 @@ void nv_setlist(struct argnod *arg,int flags, Namval_t *typ)
563561
{
564562
L_ARGNOD->nvalue = node.nvalue;
565563
L_ARGNOD->nvflag = node.nvflag;
566-
L_ARGNOD->dynscope = node.dynscope;
567564
L_ARGNOD->nvfun = node.nvfun;
568565
}
569566
sh.prefix = prefix;
@@ -600,7 +597,6 @@ void nv_setlist(struct argnod *arg,int flags, Namval_t *typ)
600597
mp = nv_search(cp,vartree,NV_ADD|NV_NOSCOPE);
601598
mp->nvname = np->nvname; /* put_lang() (init.c) compares nvname pointers */
602599
mp->nvflag = np->nvflag;
603-
mp->dynscope = np->dynscope;
604600
mp->nvsize = np->nvsize;
605601
mp->nvfun = nv_cover(np);
606602
}
@@ -667,7 +663,6 @@ void nv_setlist(struct argnod *arg,int flags, Namval_t *typ)
667663
{
668664
L_ARGNOD->nvalue = node.nvalue;
669665
L_ARGNOD->nvflag = node.nvflag;
670-
L_ARGNOD->dynscope = node.dynscope;
671666
L_ARGNOD->nvfun = node.nvfun;
672667
}
673668
}
@@ -1575,11 +1570,7 @@ Namval_t *nv_open(const char *name, Dt_t *root, int flags)
15751570
savesub = sub;
15761571
sh.prefix = prefix;
15771572
}
1578-
nv_onattr(np, flags&NV_ATTRIBUTES);
1579-
if(flags&NV_DYNAMIC)
1580-
np->dynscope = 1;
1581-
else
1582-
np->dynscope = 0;
1573+
nv_onattr(np, flags&~(NV_ATTRIBUTES|NV_OPENMASK));
15831574
}
15841575
else if(c)
15851576
{
@@ -2201,8 +2192,6 @@ static int scanfilter(Namval_t *np, struct scan *sp)
22012192
return 0;
22022193
if(sp->scanmask==NV_TABLE && nv_isvtree(np))
22032194
np_flags = NV_TABLE;
2204-
else if(np->dynscope==1)
2205-
np_flags |= NV_DYNAMIC;
22062195
if(sp->scanmask?(np_flags&sp->scanmask)==sp->scanflags:(!sp->scanflags || (np_flags&sp->scanflags)))
22072196
{
22082197
if(tp && tp->mapname)
@@ -2858,7 +2847,7 @@ void nv_newattr (Namval_t *np, unsigned newatts, int size)
28582847
else if(size==NV_FLTSIZEZERO)
28592848
np->nvsize = 0;
28602849
nv_offattr(np, ~NV_NOFREE);
2861-
nv_onattr(np, newatts);
2850+
nv_onattr(np, newatts&~(NV_OPENMASK));
28622851
return;
28632852
}
28642853
if(size==NV_FLTSIZEZERO)
@@ -2878,7 +2867,7 @@ void nv_newattr (Namval_t *np, unsigned newatts, int size)
28782867
{
28792868
nv_setsize(np,size);
28802869
np->nvflag &= NV_ARRAY;
2881-
np->nvflag |= newatts;
2870+
np->nvflag |= newatts&~(NV_OPENMASK);
28822871
goto skip;
28832872
}
28842873
#endif /* SHOPT_FIXEDARRAY */
@@ -2937,8 +2926,8 @@ void nv_newattr (Namval_t *np, unsigned newatts, int size)
29372926
_nv_unset(np,NV_EXPORT);
29382927
nv_setsize(np,size);
29392928
np->nvflag &= (NV_ARRAY|NV_NOFREE);
2940-
np->nvflag |= newatts;
2941-
if (cp)
2929+
np->nvflag |= newatts&~(NV_OPENMASK);
2930+
if(cp)
29422931
{
29432932
if(!mp)
29442933
nv_putval (np, cp, NV_RDONLY);

src/cmd/ksh93/sh/nvdisc.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,8 @@ int nv_clone(Namval_t *np, Namval_t *mp, int flags)
894894
{
895895
Namfun_t *fp, *fpnext;
896896
const char *val = mp->nvalue;
897-
unsigned short flag = mp->nvflag;
898-
unsigned short size = mp->nvsize;
897+
uint32_t flag = mp->nvflag;
898+
uint32_t size = mp->nvsize;
899899
for(fp=mp->nvfun; fp; fp=fpnext)
900900
{
901901
fpnext = fp->next;

src/cmd/ksh93/sh/nvtree.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ void nv_attribute(Namval_t *np,Sfio_t *out,char *prefix,int noname)
404404
else if((!np->nvalue||np->nvalue==Empty) && nv_isattr(np,~NV_NOFREE)==NV_MINIMAL && strcmp(np->nvname,"_"))
405405
sfputr(out,prefix,' ');
406406
}
407-
if(np->dynscope)
407+
if(nv_isattr(np,NV_DYNAMIC))
408408
sfprintf(out,"%s -D ",prefix);
409409
return;
410410
}
@@ -435,7 +435,7 @@ void nv_attribute(Namval_t *np,Sfio_t *out,char *prefix,int noname)
435435
else if(prefix && *prefix)
436436
{
437437
sfputr(out,prefix,' ');
438-
if(np->dynscope)
438+
if(nv_isattr(np,NV_DYNAMIC))
439439
sfprintf(out,"-D ");
440440
}
441441
for(tp = shtab_attributes; *tp->sh_name;tp++)

src/cmd/ksh93/sh/nvtype.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,8 @@ static Namval_t *create_type(Namval_t *np,const char *name,int flag,Namfun_t *fp
481481
n = (cp-1) -name;
482482
if(dp->numnodes && dp->strsize<0)
483483
{
484-
char *base = (char*)np-sizeof(Dtlink_t);
485-
int m=strlen(np->nvname);
484+
char *base = (char*)np-(NV_MINSZ-sizeof(Dtlink_t));
485+
size_t m = strlen(np->nvname);
486486
while((nq=nv_namptr(base,++i)) && strncmp(nq->nvname,np->nvname,m)==0)
487487
{
488488
if(nq->nvname[m]=='.' && strncmp(name,&nq->nvname[m+1],n)==0 && nq->nvname[m+n+1]==0)

src/cmd/ksh93/sh/xec.c

+14-12
Original file line numberDiff line numberDiff line change
@@ -3083,19 +3083,21 @@ int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
30833083
if(dtret)
30843084
{
30853085
/*
3086-
* Dynamic variables are implemented by being marked via np->dynscope, then
3087-
* imported into nested functions via the nv_scan call below with scanflags
3088-
* set to NV_DYNAMIC. The separate variable is necessary because np->nvflag
3089-
* is an unsigned short and cannot hold the NV_DYNAMIC bitflag. It cannot
3090-
* be changed to an unsigned int because the codebase makes too many assumptions
3091-
* about its size (cf. https://github.com/att/ast/issues/1038).
3086+
* Dynamic variables are implemented by being imported into nested functions
3087+
* via the nv_scan call.
30923088
*
3093-
* The old method ksh93v- uses for its bash mode creates a viewport between
3094-
* sh.var_tree and sh.var_base with the help of a sh.st.var_local pointer.
3095-
* This could fake dynamic scoping convincingly for the bash mode, but the
3096-
* ksh93v- code only manages to create a global scope local to the top level
3097-
* function (i.e., nested functions have no scoping at all and their variables
3098-
* leak into the calling function.)
3089+
* TODO: The old method ksh93v- uses for its bash mode creates a viewport
3090+
* between sh.var_tree and sh.var_base with the help of a sh.st.var_local
3091+
* pointer. This could fake dynamic scoping convincingly for the bash mode,
3092+
* but the ksh93v- code only manages to create a global scope local to the top
3093+
* level function (i.e., nested functions have no scoping at all and their
3094+
* variables leak into the calling function). That code could to be robustified
3095+
* to perhaps create a viewport between the parent function's scope and that of
3096+
* the child function, but that runs the risk of breaking static scoping.
3097+
* Alternatively, the current method could be altered to simply copy or move
3098+
* dynamic local variables from the child function back into the parent function
3099+
* when function execution ends; that has its own set of associated risks.
3100+
* Cf. https://github.com/ksh93/ksh/pull/703#issuecomment-1898680500
30993101
*/
31003102
nv_scan(prevscope->save_tree, local_exports, NULL, 0, NV_EXPORT|NV_DYNAMIC|NV_NOSCOPE);
31013103
}

0 commit comments

Comments
 (0)