hush: fix a nommu bug where a part of function body is lost if run in a pipe
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Sep 2015 04:22:10 +0000 (06:22 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Sep 2015 04:22:10 +0000 (06:22 +0200)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/hush.c
shell/hush_test/hush-misc/nommu3.right [new file with mode: 0644]
shell/hush_test/hush-misc/nommu3.tests [new file with mode: 0755]

index 3ca04494cc55b9c03a4d4d4c1d6d5471211ad2ba..752080a64b34611af430ba5716d9184a22663954 100644 (file)
@@ -3161,11 +3161,29 @@ static int reserved_word(o_string *word, struct parse_context *ctx)
                old->command->group = ctx->list_head;
                old->command->cmd_type = CMD_NORMAL;
 # if !BB_MMU
-               o_addstr(&old->as_string, ctx->as_string.data);
-               o_free_unsafe(&ctx->as_string);
-               old->command->group_as_string = xstrdup(old->as_string.data);
-               debug_printf_parse("pop, remembering as:'%s'\n",
-                               old->command->group_as_string);
+               /* At this point, the compound command's string is in
+                * ctx->as_string... except for the leading keyword!
+                * Consider this example: "echo a | if true; then echo a; fi"
+                * ctx->as_string will contain "true; then echo a; fi",
+                * with "if " remaining in old->as_string!
+                */
+               {
+                       char *str;
+                       int len = old->as_string.length;
+                       /* Concatenate halves */
+                       o_addstr(&old->as_string, ctx->as_string.data);
+                       o_free_unsafe(&ctx->as_string);
+                       /* Find where leading keyword starts in first half */
+                       str = old->as_string.data + len;
+                       if (str > old->as_string.data)
+                               str--; /* skip whitespace after keyword */
+                       while (str > old->as_string.data && isalpha(str[-1]))
+                               str--;
+                       /* Ugh, we're done with this horrid hack */
+                       old->command->group_as_string = xstrdup(str);
+                       debug_printf_parse("pop, remembering as:'%s'\n",
+                                       old->command->group_as_string);
+               }
 # endif
                *ctx = *old;   /* physical copy */
                free(old);
@@ -4248,7 +4266,7 @@ static struct pipe *parse_stream(char **pstring,
                                pi = NULL;
                        }
 #if !BB_MMU
-                       debug_printf_parse("as_string '%s'\n", ctx.as_string.data);
+                       debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
                        if (pstring)
                                *pstring = ctx.as_string.data;
                        else
@@ -4399,7 +4417,7 @@ static struct pipe *parse_stream(char **pstring,
                        ) {
                                o_free(&dest);
 #if !BB_MMU
-                               debug_printf_parse("as_string '%s'\n", ctx.as_string.data);
+                               debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
                                if (pstring)
                                        *pstring = ctx.as_string.data;
                                else
@@ -4639,9 +4657,6 @@ static struct pipe *parse_stream(char **pstring,
                                 * with redirect_opt_num(), but bash doesn't do it.
                                 * "echo foo 2| cat" yields "foo 2". */
                                done_command(&ctx);
-#if !BB_MMU
-                               o_reset_to_empty_unquoted(&ctx.as_string);
-#endif
                        }
                        goto new_cmd;
                case '(':
diff --git a/shell/hush_test/hush-misc/nommu3.right b/shell/hush_test/hush-misc/nommu3.right
new file mode 100644 (file)
index 0000000..da1534b
--- /dev/null
@@ -0,0 +1,2 @@
+Ok
+0
diff --git a/shell/hush_test/hush-misc/nommu3.tests b/shell/hush_test/hush-misc/nommu3.tests
new file mode 100755 (executable)
index 0000000..0aca67a
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+func()
+{
+       while read p; do echo "$p"; done
+}
+
+pipe_to_func()
+{
+       # We had a NOMMU bug which caused "echo Ok |" part ot be lost
+       echo Ok | func
+}
+
+pipe_to_func | cat
+echo $?