--- /dev/null
+--- busybox-1.18.4/shell/hush.c
++++ busybox-1.18.4-hush/shell/hush.c
+@@ -427,6 +427,15 @@ enum {
+ /* Used for initialization: o_string foo = NULL_O_STRING; */
+ #define NULL_O_STRING { NULL }
+
++#ifndef debug_printf_parse
++static const char *const assignment_flag[] = {
++ "MAYBE_ASSIGNMENT",
++ "DEFINITELY_ASSIGNMENT",
++ "NOT_ASSIGNMENT",
++ "WORD_IS_KEYWORD",
++};
++#endif
++
+ /* I can almost use ordinary FILE*. Is open_memstream() universally
+ * available? Where is it documented? */
+ typedef struct in_str {
+@@ -2885,24 +2894,24 @@ static const struct reserved_combo* matc
+ */
+ static const struct reserved_combo reserved_list[] = {
+ # if ENABLE_HUSH_IF
+- { "!", RES_NONE, NOT_ASSIGNMENT , 0 },
+- { "if", RES_IF, WORD_IS_KEYWORD, FLAG_THEN | FLAG_START },
+- { "then", RES_THEN, WORD_IS_KEYWORD, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
+- { "elif", RES_ELIF, WORD_IS_KEYWORD, FLAG_THEN },
+- { "else", RES_ELSE, WORD_IS_KEYWORD, FLAG_FI },
+- { "fi", RES_FI, NOT_ASSIGNMENT , FLAG_END },
++ { "!", RES_NONE, NOT_ASSIGNMENT , 0 },
++ { "if", RES_IF, MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
++ { "then", RES_THEN, MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
++ { "elif", RES_ELIF, MAYBE_ASSIGNMENT, FLAG_THEN },
++ { "else", RES_ELSE, MAYBE_ASSIGNMENT, FLAG_FI },
++ { "fi", RES_FI, NOT_ASSIGNMENT , FLAG_END },
+ # endif
+ # if ENABLE_HUSH_LOOPS
+- { "for", RES_FOR, NOT_ASSIGNMENT , FLAG_IN | FLAG_DO | FLAG_START },
+- { "while", RES_WHILE, WORD_IS_KEYWORD, FLAG_DO | FLAG_START },
+- { "until", RES_UNTIL, WORD_IS_KEYWORD, FLAG_DO | FLAG_START },
+- { "in", RES_IN, NOT_ASSIGNMENT , FLAG_DO },
+- { "do", RES_DO, WORD_IS_KEYWORD, FLAG_DONE },
+- { "done", RES_DONE, NOT_ASSIGNMENT , FLAG_END },
++ { "for", RES_FOR, NOT_ASSIGNMENT , FLAG_IN | FLAG_DO | FLAG_START },
++ { "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
++ { "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
++ { "in", RES_IN, NOT_ASSIGNMENT , FLAG_DO },
++ { "do", RES_DO, MAYBE_ASSIGNMENT, FLAG_DONE },
++ { "done", RES_DONE, NOT_ASSIGNMENT , FLAG_END },
+ # endif
+ # if ENABLE_HUSH_CASE
+- { "case", RES_CASE, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_START },
+- { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END },
++ { "case", RES_CASE, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_START },
++ { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END },
+ # endif
+ };
+ const struct reserved_combo *r;
+@@ -2968,6 +2977,7 @@ static int reserved_word(o_string *word,
+ ctx->ctx_res_w = r->res;
+ ctx->old_flag = r->flag;
+ word->o_assignment = r->assignment_flag;
++ debug_printf_parse("word->o_assignment='%s'\n", assignment_flag[word->o_assignment]);
+
+ if (ctx->old_flag & FLAG_END) {
+ struct parse_context *old;
+@@ -3034,18 +3044,6 @@ static int done_word(o_string *word, str
+ debug_printf_parse("word stored in rd_filename: '%s'\n", word->data);
+ ctx->pending_redirect = NULL;
+ } else {
+- /* If this word wasn't an assignment, next ones definitely
+- * can't be assignments. Even if they look like ones. */
+- if (word->o_assignment != DEFINITELY_ASSIGNMENT
+- && word->o_assignment != WORD_IS_KEYWORD
+- ) {
+- word->o_assignment = NOT_ASSIGNMENT;
+- } else {
+- if (word->o_assignment == DEFINITELY_ASSIGNMENT)
+- command->assignment_cnt++;
+- word->o_assignment = MAYBE_ASSIGNMENT;
+- }
+-
+ #if HAS_KEYWORDS
+ # if ENABLE_HUSH_CASE
+ if (ctx->ctx_dsemicolon
+@@ -3065,8 +3063,9 @@ static int done_word(o_string *word, str
+ && ctx->ctx_res_w != RES_CASE
+ # endif
+ ) {
+- debug_printf_parse("checking '%s' for reserved-ness\n", word->data);
+- if (reserved_word(word, ctx)) {
++ int reserved = reserved_word(word, ctx);
++ debug_printf_parse("checking for reserved-ness: %d\n", reserved);
++ if (reserved) {
+ o_reset_to_empty_unquoted(word);
+ debug_printf_parse("done_word return %d\n",
+ (ctx->ctx_res_w == RES_SNTX));
+@@ -3087,6 +3086,23 @@ static int done_word(o_string *word, str
+ "groups and arglists don't mix\n");
+ return 1;
+ }
++
++ /* If this word wasn't an assignment, next ones definitely
++ * can't be assignments. Even if they look like ones. */
++ if (word->o_assignment != DEFINITELY_ASSIGNMENT
++ && word->o_assignment != WORD_IS_KEYWORD
++ ) {
++ word->o_assignment = NOT_ASSIGNMENT;
++ } else {
++ if (word->o_assignment == DEFINITELY_ASSIGNMENT) {
++ command->assignment_cnt++;
++ debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
++ }
++ debug_printf_parse("word->o_assignment was:'%s'\n", assignment_flag[word->o_assignment]);
++ word->o_assignment = MAYBE_ASSIGNMENT;
++ }
++ debug_printf_parse("word->o_assignment='%s'\n", assignment_flag[word->o_assignment]);
++
+ if (word->has_quoted_part
+ /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */
+ && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL)
+@@ -4105,6 +4121,7 @@ static struct pipe *parse_stream(char **
+ && is_well_formed_var_name(dest.data, '=')
+ ) {
+ dest.o_assignment = DEFINITELY_ASSIGNMENT;
++ debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
+ }
+ continue;
+ }
+@@ -4154,6 +4171,7 @@ static struct pipe *parse_stream(char **
+ heredoc_cnt = 0;
+ }
+ dest.o_assignment = MAYBE_ASSIGNMENT;
++ debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
+ ch = ';';
+ /* note: if (is_blank) continue;
+ * will still trigger for us */
+@@ -4203,6 +4221,7 @@ static struct pipe *parse_stream(char **
+ }
+ done_pipe(&ctx, PIPE_SEQ);
+ dest.o_assignment = MAYBE_ASSIGNMENT;
++ debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
+ /* Do we sit outside of any if's, loops or case's? */
+ if (!HAS_KEYWORDS
+ IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
+@@ -4309,6 +4328,7 @@ static struct pipe *parse_stream(char **
+ /* ch is a special char and thus this word
+ * cannot be an assignment */
+ dest.o_assignment = NOT_ASSIGNMENT;
++ debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
+ }
+
+ /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
+@@ -4406,6 +4426,7 @@ static struct pipe *parse_stream(char **
+ /* We just finished a cmd. New one may start
+ * with an assignment */
+ dest.o_assignment = MAYBE_ASSIGNMENT;
++ debug_printf_parse("dest.o_assignment='%s'\n", assignment_flag[dest.o_assignment]);
+ break;
+ case '&':
+ if (done_word(&dest, &ctx)) {