[U-Boot] [PATCH] hush: when a variable expansion is empty, don't drop the parameter

Stephen Warren swarren at wwwdotorg.org
Thu Feb 27 07:55:06 CET 2014


The following shell command fails:

if test -z "$x"; then echo "zero"; else echo "non-zero"; fi

(assuming $x does not exist, it prints "non-zero" rather than "zero").

... since "$x" expands to nothing, and the argument is completely
dropped, causing too few to be passed to -z, causing cmd_test() to
error out early.

This is because when variable expansions are processed by make_string(),
the expanded results are concatenated back into a new string. However,
no quoting is applied when doing so, so any empty variables simply don't
generate any parameter when the combined string is parsed again.

Fix this by explicitly replacing any empty expansion with an empty pair
of quotes, so that an argument is still generated.

Reported-by: Russell King <linux at arm.linux.org.uk>
Signed-off-by: Stephen Warren <swarren at wwwdotorg.org>
---
Hmm. I wonder if this causes other problems, such as:

if test -z $x; then echo "zero"; else echo "non-zero"; fi

I guess we should only quote the expansion if the input string had quotes
around the text being expanded, but I'm not sure if we can know that.
Perhaps more investigation is needed:-( Although... I /guess/ that case
is rarer, so this patch still improves things?
---
 common/hush.c     | 8 ++++++--
 test/command_ut.c | 6 ++++++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/common/hush.c b/common/hush.c
index 3f3a79c..7a67706 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -116,7 +116,7 @@
 #endif
 #endif
 #define SPECIAL_VAR_SYMBOL 03
-#define SUBSTED_VAR_SYMBOL 04
+#define q 04
 #ifndef __U_BOOT__
 #define FLAG_EXIT_FROM_LOOP 1
 #define FLAG_PARSE_SEMICOLON (1 << 1)		/* symbol ';' is special for parser */
@@ -3594,12 +3594,15 @@ static char * make_string(char ** inp)
 	int len = 2;
 	char *noeval_str;
 	int noeval = 0;
+	char *empty = "\"\"";
 
 	noeval_str = get_local_var("HUSH_NO_EVAL");
 	if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0')
 		noeval = 1;
 	for (n = 0; inp[n]; n++) {
 		p = insert_var_value_sub(inp[n], noeval);
+		if (!*p)
+			p = empty;
 		str = xrealloc(str, (len + strlen(p)));
 		if (n) {
 			strcat(str, " ");
@@ -3608,7 +3611,8 @@ static char * make_string(char ** inp)
 		}
 		strcat(str, p);
 		len = strlen(str) + 3;
-		if (p != inp[n]) free(p);
+		if (p != inp[n] && p != empty)
+			free(p);
 	}
 	len = strlen(str);
 	*(str + len) = '\n';
diff --git a/test/command_ut.c b/test/command_ut.c
index 620a297..6074b0e 100644
--- a/test/command_ut.c
+++ b/test/command_ut.c
@@ -137,6 +137,12 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	HUSH_TEST(or_1_0_inv_inv, "! ! aaa = aaa -o ! ! bbb != bbb", y);
 	HUSH_TEST(or_1_1_inv_inv, "! ! aaa = aaa -o ! ! bbb = bbb", y);
 
+	run_command("setenv ut_var_nonexistent", 0);
+	run_command("setenv ut_var_exists 1", 0);
+	HUSH_TEST(z_varexp, "-z \"$ut_var_nonexistent\"", y);
+	HUSH_TEST(z_varexp, "-z \"$ut_var_exists\"", n);
+	run_command("setenv ut_var_exists", 0);
+
 #ifdef CONFIG_SANDBOX
 	/*
 	 * File existence
-- 
1.8.3.2



More information about the U-Boot mailing list