diff options
-rw-r--r-- | bin/ksh/eval.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/bin/ksh/eval.c b/bin/ksh/eval.c index 03b10eef642..bf8e43fb042 100644 --- a/bin/ksh/eval.c +++ b/bin/ksh/eval.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eval.c,v 1.60 2018/04/09 17:53:36 tobias Exp $ */ +/* $OpenBSD: eval.c,v 1.61 2018/07/08 13:18:44 anton Exp $ */ /* * Expansion - quoting, separation, substitution, globbing @@ -58,6 +58,8 @@ static char *tilde(char *); static char *homedir(char *); static void alt_expand(XPtrV *, char *, char *, char *, int); +static struct tbl *varcpy(struct tbl *); + /* compile and expand word */ char * substitute(const char *cp, int f) @@ -190,7 +192,8 @@ expand(char *cp, /* input word */ doblank = 0; make_magic = 0; word = (f&DOBLANK) ? IFS_WS : IFS_WORD; - st_head.next = NULL; + + memset(&st_head, 0, sizeof(st_head)); st = &st_head; while (1) { @@ -305,7 +308,7 @@ expand(char *cp, /* input word */ st->stype = stype; st->base = Xsavepos(ds, dp); st->f = f; - st->var = x.var; + st->var = varcpy(x.var); st->quote = quote; /* skip qualifier(s) */ if (stype) @@ -577,7 +580,7 @@ expand(char *cp, /* input word */ Xinit(ds, dp, 128, ATEMP); } if (c == 0) - return; + goto done; if (word != IFS_NWS) word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS; } else { @@ -682,6 +685,14 @@ expand(char *cp, /* input word */ word = IFS_WORD; } } + +done: + for (st = &st_head; st != NULL; st = st->next) { + if (st->var == NULL || (st->var->flag & RDONLY) == 0) + continue; + + afree(st->var, ATEMP); + } } /* @@ -1286,3 +1297,23 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo) } return; } + +/* + * Copy the given variable if it's flagged as read-only. + * Such variables have static storage and only one can therefore be referenced + * at a time. + * This is necessary in order to allow variable expansion expressions to refer + * to multiple read-only variables. + */ +static struct tbl * +varcpy(struct tbl *vp) +{ + struct tbl *cpy; + + if ((vp->flag & RDONLY) == 0) + return vp; + + cpy = alloc(sizeof(struct tbl), ATEMP); + memcpy(cpy, vp, sizeof(struct tbl)); + return cpy; +} |