commit:     01eed688501d74201f6fd319e4f55330c7193e61
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Sat Jan 31 01:51:27 2026 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Fri Feb  6 01:45:14 2026 +0000
URL:        
https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=01eed688

Handle positional parameters beyond $9 in parallel_run()

So as to be compatible with POSIX sh(1), each parallel_run() worker
iterates over a distinct sequence of integers, each of which is
distanced from one another by the chosen number of workers. These
integers are used to dereference the values of distinct positional
parameters, with the aid of the eval builtin.

Alas, I discovered a serious bug, whereby positional parameters beyond
"$9" are not actually dereferenced.

$ parallel_run 1 echo {a..z} | xargs
a b c d e f g h i a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6

This is caused by attempting to expand parameters such as "$10", "$11",
"$12" and so on. Note that the effect of expanding "$10" is to expand
"$1", along with a trailing "0". Address this issue by enclosing the
digits within curly braces. Thus, "${10}", "${11}", "${12} and so on.

$ parallel_run 1 echo {a..z} | xargs
a b c d e f g h i j k l m n o p q r s t u v w x y z

Additionally, add a test case.

Bug: https://bugs.gentoo.org/940103
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>

 functions.sh   |  2 +-
 test-functions | 13 +++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/functions.sh b/functions.sh
index 9172788..06af1e1 100644
--- a/functions.sh
+++ b/functions.sh
@@ -437,7 +437,7 @@ parallel_run()
                while [ "$(( w += 1 ))" -le "${workers}" ]; do
                        i=$w
                        while [ "$i" -le "$#" ]; do
-                               eval "arg=\$${i}"
+                               eval "arg=\${$i}"
                                if ! "${cmd}" "${arg}"; then
                                        mkdir -p -- "${statedir}"
                                fi

diff --git a/test-functions b/test-functions
index 4bd7643..989c0e9 100755
--- a/test-functions
+++ b/test-functions
@@ -786,6 +786,18 @@ test_parallel_run() {
        iterate_tests 4 "$@"
 }
 
+test_parallel_run_deref() {
+       set -- eq 0
+
+       callback() {
+               test_description="quote_args parameter derefencing test 
(expecting cksum 3992977419)"
+               set -- a b c d e f g h i j k l m n o p q r s t u v w x y z
+               test "$(parallel_run 1 echo "$@" | cksum)" = "3992977419 52"
+       }
+
+       iterate_tests 2 "$@"
+}
+
 test_is_anyof() {
        set -- \
                ge  1  N/A  N/A  N/A  \
@@ -1282,6 +1294,7 @@ else
        #test_hr || rc=1
        test_whenceforth || rc=1
        test_parallel_run || rc=1
+       test_parallel_run_deref || rc=1
        test_is_anyof || rc=1
        #test_is_subset || rc=1
        test_trueof_all || rc=1

Reply via email to