From e76971b0a7919f13ce9c5eb4b194f93d8c8a9645 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 12 Aug 2026 15:16:32 -0500 Subject: [PATCH] Fix prefix assignment in pipelines. --- tests/sh.test | 6 ++++++ toys/pending/sh.c | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/sh.test b/tests/sh.test index 7225fa2d..ce1fa6de 100644 --- a/tests/sh.test +++ b/tests/sh.test @@ -170,6 +170,12 @@ testing 'assignment with not is persistent' '! a=b; echo $a $?' 'b 1\n' '' '' testing '! ! redirect prefix assignment exported not persistent' \ '! ! > file.txt A=B env; echo $?; grep ^A= file.txt; echo $A' \ '0\nA=B\n\n' '' '' +testing 'prefix assignment pipe-local' 'ABC=abc; ABC=def true | echo $ABC' \ + 'abc\n' '' '' +testing 'prefix assignment exports' \ + 'ABC=abc; ABC=def env | grep ^ABC=; echo $ABC' 'ABC=def\nabc\n' '' '' +testing 'redundant prefix assignment' \ + 'ABC=abc; ABC=def ABC=ghi env | grep ^ABC=; echo $ABC' 'ABC=ghi\nabc\n' '' '' $BROKEN testing '$_ with functions' 'true; x(){ echo $_;}; x abc; echo $_' \ 'true\nabc\n' '' '' diff --git a/toys/pending/sh.c b/toys/pending/sh.c index 1c3de708..25ac85af 100644 --- a/toys/pending/sh.c +++ b/toys/pending/sh.c @@ -1041,6 +1041,7 @@ bad: static struct sh_vars *setvar_long(char *s, int freeable, struct sh_fcall *ff) { struct sh_vars *vv = 0, *was; + struct sh_fcall *new; char *ss; if (!s) return 0; @@ -1053,7 +1054,9 @@ static struct sh_vars *setvar_long(char *s, int freeable, struct sh_fcall *ff) } // Add if necessary, set value, and remove again if we added but set failed - if (!(was = vv = findvar(s, &ff))) (vv = addvar(s, ff))->flags = VAR_NOFREE; + if (!(was = vv = findvar(s, &new)) || (ff && new!=ff)) + (vv = addvar(s, ff = ff ? : TT.ff->prev))->flags = VAR_NOFREE; + else ff = new; if (!setvar_found(s, freeable, vv)) { if (!was) memmove(vv, vv+1, sizeof(struct sh_vars)*(ff->varslen-- -(vv-ff->vars))); @@ -1068,7 +1071,7 @@ static struct sh_vars *setvar_long(char *s, int freeable, struct sh_fcall *ff) // Returns sh_vars * or 0 for failure (readonly, etc) static struct sh_vars *setvar(char *str) { - return setvar_long(str, 1, TT.ff->prev); + return setvar_long(str, 1, 0); } @@ -2999,7 +3002,7 @@ static struct sh_process *run_command(int local) if ((ss = expand_one_arg(s = prefix.v[jj], NO_IFS))) { if (!local && ss==s) ss = xstrdup(ss); - if ((vv = setvar_long(ss, ss!=s, local ? TT.ff : TT.ff->prev))) + if ((vv = setvar_long(ss, ss!=s, local ? TT.ff : 0))) if (local) vv->flags |= VAR_EXPORT; } else pp->exit = 1; } -- 2.39.5