summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/ksh/eval.c39
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;
+}