bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: simple prob?


From: Greg Wooledge
Subject: Re: simple prob?
Date: Fri, 2 Jul 2021 08:00:44 -0400

On Fri, Jul 02, 2021 at 09:09:34AM +0200, Phi Debian wrote:
> PW$ function njobs
> > { [ "$1" != "n" ] && typeset -n n="$1"
> >    typeset -a t ; readarray t <<<"$(jobs)" ;n=${#t[@]}
> > }

<<<$() is a poor imitation of < <() which is what you really want.

readarray -t t < <(jobs); n=${#t[@]}

Combining <<< and $() only gives an approximation of the same result
(the command substitution strips off all trailing newline characters,
and then the here-string syntax appends one newline), and it's less
efficient, because it involves slurping the entire input into memory,
then writing it out to a temporary file, then opening the temporary
file for input and unlinking it, then reading it back in a second time.

Using < <() avoids the newline alterations and the temporary file.

(Note: in some sufficiently new versions of bash, there may not be a
temporary file in some cases.  But it's still not the best solution,
as it still involves storing and reading the whole output multiple times.)


Stepping back a moment, you're using the name reference version of the
"pass an output variable by reference" strategy.  This requires bash 4.3,
which is reasonable, and it requires some additional sanity checks which
you did not show.

What's really interesting to me is that you did a *partial* sanity check,
refusing to create a circular name reference if the user passed "n"
as their output variable name.  But you forgot to check for "t", which is
another local variable you're using.  Also, in Linda's original example,
the output variable was literally named "n", so choosing that as your
name reference and explicitly disallowing it is a really spiteful choice.

Finally, you didn't do any sanity checking of the output variable name
(beyond comparing it to one of your two local variable names), so your
function is susceptible to the same code injection attacks we discussed
earlier in the thread.

unicorn:~$ njobs_ref() { typeset -n n="$1"; n=42; }
unicorn:~$ njobs_ref 'x[0$(date>&2)]'
Fri Jul  2 07:54:49 EDT 2021

As I mentioned a few days ago, all variants of the "pass a variable name
by reference" method are basically equivalent to each other, and all
of them need input sanity checking in order to avoid code injections.
(Some of the variants avoid *some* flavors of code injection, but none of
them avoid this one.)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]