commit:     6f9971e54dab95c86f0eced52574a586916a5e4b
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Fri Jul 18 21:01:08 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Jul 22 22:29:37 2025 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=6f9971e5

isolated-functions.sh: render assert() insensitive to the value of IFS

The purpose of the assert() function is to forward the positional
parameters to the die() function, provided that any of the elements of
the 'PIPESTATUS' array variable are non-zero. However, the function is
defective because it is beholden to the prevailing value of IFS.

Consider the following.

$ IFS=1
$ set -x; true | false | true; assert
+ true
+ false
+ true
+ assert
+ local x pipestatus=01110
+ for x in ${pipestatus}
+ [[ 0 -eq 0 ]]
+ for x in ${pipestatus}
+ [[ '' -eq 0 ]]
+ for x in ${pipestatus}
+ [[ '' -eq 0 ]]
+ for x in ${pipestatus}
+ [[ 0 -eq 0 ]]

It can be seen that the elements of 'PIPESTATUS' are joined by "1",
forming the string, "01110", which is assigned to the 'pipestatus'
variable. Next, the for command is tasked with iterating over the words
produced by an unquoted expansion of this variable. Since "1" is acting
as a field terminator, the for loop iterates over two instances of "0",
and two instances of the null string, all of which are arithmetically
equal to 0. Consequently, die() is never called, though it ought to be.

Address this issue by forming an arithmetic expression from the elements
of 'PIPESTATUS' and having a single invocation of the let builtin
evaluate it.

$ IFS=1
$ set -x; true | false | true; assert
+ true
+ false
+ true
+ assert
+ IFS='|'
+ expression='0|1|0'
+ let '! expression'
+ die

Bug: https://bugs.gentoo.org/25929
Fixes: c86c1391904231287824676cc663d7e3eddd8954
See-also: 038146623c0cdca0ba2038ee7837c3a2170b35de
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>

 bin/isolated-functions.sh | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh
index 6db0340926..0c83e5d963 100644
--- a/bin/isolated-functions.sh
+++ b/bin/isolated-functions.sh
@@ -23,10 +23,7 @@ fi
 shopt -s expand_aliases
 
 assert() {
-       local x pipestatus=${PIPESTATUS[*]}
-       for x in ${pipestatus} ; do
-               [[ ${x} -eq 0 ]] || die "$@"
-       done
+       IFS='|' expression=${PIPESTATUS[*]} let '! expression' || die "$@"
 }
 
 shopt -s extdebug

Reply via email to