summaryrefslogtreecommitdiff
path: root/shell/msh.c
diff options
context:
space:
mode:
authorEric Andersen2004-09-02 23:13:10 +0000
committerEric Andersen2004-09-02 23:13:10 +0000
commitfd7a4c8c2887187e901809d89997deefb8b99d97 (patch)
tree70ea04a5934546b070f3e0c403629fe4da7aa444 /shell/msh.c
parent7b08cdd98cdf99b0d2bd622566e9288d44b17529 (diff)
downloadbusybox-fd7a4c8c2887187e901809d89997deefb8b99d97.zip
busybox-fd7a4c8c2887187e901809d89997deefb8b99d97.tar.gz
Jonas Holmberg from axis dot com writes:
This patch makes msh handle variable expansion within backticks more correctly. Current behaviour (wrong): -------------------------- BusyBox v1.00-rc3 (2004.08.26-11:51+0000) Built-in shell (msh) Enter 'help' for a list of built-in commands. $ A='`echo hello`' $ echo $A `echo hello` $ echo `echo $A` hello $ New behaviour (correct): ------------------------ BusyBox v1.00-rc3 (2004.08.26-11:51+0000) Built-in shell (msh) Enter 'help' for a list of built-in commands. $ A='`echo hello`' $ echo $A `echo hello` $ echo `echo $A` `echo hello` $ The current behaviour (wrong according to standards) was actually my fault. msh handles backticks by executing a subshell (which makes it work on MMU-less systems). Executing a subshell makes it hard to only expand variables once in the parent. Therefore I export all variables that will be expanded within the backticks and let the subshell handle the expansion instead. The bug was found while searching for security leaks in CGI-scripts. Current behaviour of msh makes it easy to expand backticks by mistake in $QUERY_STRING. I recommend appling the patch before release of bb 1.00. /Jonas
Diffstat (limited to 'shell/msh.c')
-rw-r--r--shell/msh.c68
1 files changed, 46 insertions, 22 deletions
diff --git a/shell/msh.c b/shell/msh.c
index df4c3da..2fb0df7 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -299,7 +299,7 @@ static int rlookup(char *n);
static struct wdblock *glob(char *cp, struct wdblock *wb);
static int my_getc(int ec);
static int subgetc(int ec, int quoted);
-static char **makenv(int all);
+static char **makenv(int all, struct wdblock *wb);
static char **eval(char **ap, int f);
static int setstatus(int s);
static int waitfor(int lastpid, int canintr);
@@ -3032,7 +3032,7 @@ forkexec(REGISTER struct op *t, int *pin, int *pout, int act, char **wp)
if (wp[0] == NULL)
_exit(0);
- cp = rexecve(wp[0], wp, makenv(0));
+ cp = rexecve(wp[0], wp, makenv(0, NULL));
prs(wp[0]);
prs(": ");
err(cp);
@@ -3486,7 +3486,7 @@ struct op *t;
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
}
- cp = rexecve(t->words[0], t->words, makenv(0));
+ cp = rexecve(t->words[0], t->words, makenv(0, NULL));
prs(t->words[0]);
prs(": ");
err(cp);
@@ -3954,14 +3954,12 @@ static char **eval(char **ap, int f)
* names in the dictionary. Keyword assignments
* will already have been done.
*/
-static char **makenv(int all)
+static char **makenv(int all, struct wdblock *wb)
{
- REGISTER struct wdblock *wb;
REGISTER struct var *vp;
DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
- wb = NULL;
for (vp = vlist; vp; vp = vp->next)
if (all || vp->status & EXPORT)
wb = addword(vp->name, wb);
@@ -4251,6 +4249,7 @@ int quoted;
int ignore;
int ignore_once;
char *argument_list[4];
+ struct wdblock *wb = NULL;
#if __GNUC__
/* Avoid longjmp clobbering */
@@ -4323,22 +4322,47 @@ int quoted;
src++;
}
- vp = lookup(var_name);
- if (vp->value != null)
- value = (operator == '+') ? alt_value : vp->value;
- else if (operator == '?') {
- err(alt_value);
- return (0);
- } else if (alt_index && (operator != '+')) {
- value = alt_value;
- if (operator == '=')
- setval(vp, value);
- } else
- continue;
+ if (isalpha(*var_name)) {
+ /* let subshell handle it instead */
+
+ char *namep = var_name;
- while (*value && (count < LINELIM)) {
- *dest++ = *value++;
- count++;
+ *dest++ = '$';
+ if (braces)
+ *dest++ = '{';
+ while (*namep)
+ *dest++ = *namep++;
+ if (operator) {
+ char *altp = alt_value;
+ *dest++ = operator;
+ while (*altp)
+ *dest++ = *altp++;
+ }
+ if (braces)
+ *dest++ = '}';
+
+ wb = addword(lookup(var_name)->name, wb);
+ } else {
+ /* expand */
+
+ vp = lookup(var_name);
+ if (vp->value != null)
+ value = (operator == '+') ?
+ alt_value : vp->value;
+ else if (operator == '?') {
+ err(alt_value);
+ return (0);
+ } else if (alt_index && (operator != '+')) {
+ value = alt_value;
+ if (operator == '=')
+ setval(vp, value);
+ } else
+ continue;
+
+ while (*value && (count < LINELIM)) {
+ *dest++ = *value++;
+ count++;
+ }
}
} else {
*dest++ = *src++;
@@ -4383,7 +4407,7 @@ int quoted;
argument_list[2] = child_cmd;
argument_list[3] = 0;
- cp = rexecve(argument_list[0], argument_list, makenv(1));
+ cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
prs(argument_list[0]);
prs(": ");
err(cp);