busybox/shell
Denys Vlasenko 5ac04f2f02 ash: [EXPAND] Fix ifsfirst/ifslastp leak
Upstream commit:

    Date: Wed, 8 Sep 2010 20:07:26 +0800
    [EXPAND] Fix ifsfirst/ifslastp leak

    As it stands expandarg may return with a non-NULL ifslastp which
    then confuses any subsequent ifsbreakup user that doesn't clear
    it directly.

    What's worse, if we get interrupted before we hit ifsfree in
    expandarg we will leak memory.

    This patch fixes this by always calling ifsfree in expandarg
    thus ensuring that ifslastp is always NULL on the normal path.
    It also adds an ifsfree call to the RESET path to ensure that
    memory isn't leaked.

    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Fallout 1:

    Date: Mon, 18 Oct 2010 10:55:42 +0800
    [EXPAND] Fix ifsfirst/ifslastp leak in casematch

    The commit f42e443bb511ed3224f09b4fcf0772438ebdbbfa

        [EXPAND] Fix ifsfirst/ifslastp leak

    revealed yet another ifsfirst/ifslastp leak in casematch.
    Previously it was hidden because ifsfirst/ifslastp was cleared
    unconditionally on entry (which caused the leakage of those
    entries).

    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Fallout 2:

    Date: Sun, 28 Nov 2010 21:09:51 +0800
    [EXPAND] Free IFS state in evalbackcmd

    On Sun, Nov 07, 2010 at 04:04:20PM -0600, Jonathan Nieder wrote:
    > Herbert Xu wrote:
    > > commit f42e443bb511ed3224f09b4fcf0772438ebdbbfa
    > > Author: Herbert Xu <herbert@gondor.apana.org.au>
    > > Date:   Wed Sep 8 20:07:26 2010 +0800
    > >
    > >     [EXPAND] Fix ifsfirst/ifslastp leak
    >
    > Another puzzle bisecting to f42e443bb.  This one comes from the
    > grub-mkconfig script:
    >
    >  $ sh -c 'datadir=/usr/share; pkgdatadir=${datadir}/`cat`' 2>&1 | cat -A
    >  cat: M-^\^M^F^HM-4^M^F^HM-(^M^F^H: No such file or directory$
    >  cat: M-(^M^F^H: No such file or directory$
    >
    > Still reproducible with 016b529.  I'll try to find time to look into
    > it, but thought you might like to know nevertheless.

    This is the symptom of another leak.  In this case evalbackcmd
    occurs in the middle of an expansion (as it should) but the forked
    child never clears the previous IFS state.

    This patch adds the missing ifsfree call.

    This wasn't as much of a problem as the previously discovered leaks
    since all it means is that the child gets to carry around the parent's
    expansion state and the child is usually short-lived.

    Reported-by: Jonathan Nieder <jrnieder@gmail.com>
    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Fallout 3:

    Date: Tue, 15 Mar 2011 16:01:34 +0800
    [EXPAND] Free IFS state after here document expansion

    Here's another bug bisecting to f42e443bb ([EXPAND] Fix
    ifsfirst/ifslastp leak, 2010-09-08).  It was found with the following
    test case, based on the configure script for Tracker:

        dash -x -c '
                <<-_ACEOF
                $@
                _ACEOF
                exec
        ' - abcdefgh
        +
        + exec   ?a
        exec: 1: : Permission denied

    The missing ifsfree call is in expandarg when it returns to openhere
    during here document expansion.

    Reported-by: Aurelien Jarno <aurel32@debian.org>
    Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

function                                             old     new   delta
ifsfree                                                -      66     +66
ash_main                                            1490    1495      +5
argstr                                              1154    1159      +5
evalcase                                             275     270      -5
expandarg                                            972     888     -84
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/2 up/down: 76/-89)            Total: -13 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2016-10-27 14:46:50 +02:00
..
ash_test ash: [PARSER] Recognise here-doc delimiters terminated by EOF 2016-10-26 16:26:45 +02:00
hush_test ash: [PARSER] Recognise here-doc delimiters terminated by EOF 2016-10-26 16:26:45 +02:00
ash_doc.txt ash: fix TRACE commands 2009-03-19 23:09:58 +00:00
ash_ptr_hack.c *: make GNU licensing statement forms more regular 2010-08-16 20:14:46 +02:00
ash.c ash: [EXPAND] Fix ifsfirst/ifslastp leak 2016-10-27 14:46:50 +02:00
brace.txt hush: wait for cmd to complete, and immediately store its exitcode in $? 2009-11-15 19:58:19 +01:00
Config.src config: disentangle PREFER_APPLETS from SH_STANDALONE and SH_NOFORK 2016-07-22 18:48:38 +02:00
cttyhack.c cttyhack: handle multiple consoles found in sysfs 2012-02-04 21:55:01 +01:00
hush_doc.txt hush: implement break and continue 2008-07-28 23:04:34 +00:00
hush_leaktool.sh hush: fix "export not_yet_defined_var", fix parsing of "cmd | }" 2009-04-19 23:07:51 +00:00
hush.c ash: [SHELL] Expand ENV before using it 2016-10-27 11:28:59 +02:00
Kbuild.src *: make GNU licensing statement forms more regular 2010-08-16 20:14:46 +02:00
match.c shell/match.c: shrink by dropping double bool inversion 2010-09-12 15:06:42 +02:00
match.h hush: optimize #[#] and %[%] for speed. size -2 bytes. 2010-09-04 21:21:07 +02:00
math.c typo fix in comment 2014-11-20 01:43:30 +01:00
math.h move endofname() to libbb 2013-02-26 00:36:53 +01:00
random.c ash,hush: fix a thinko about 2^64-1 factorization 2014-03-15 09:25:46 +01:00
random.h ash,hush: improve randomness of $RANDOM, add easy-ish way to test it 2014-03-13 12:52:43 +01:00
README update shell/README 2010-05-20 12:56:14 +02:00
README.job
shell_common.c ash: [VAR] Initialise OPTIND after importing environment 2016-09-30 14:46:41 +02:00
shell_common.h ash: [VAR] Initialise OPTIND after importing environment 2016-09-30 14:46:41 +02:00

http://www.opengroup.org/onlinepubs/9699919799/
Open Group Base Specifications Issue 7


http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html
Shell & Utilities

It says that any of the standard utilities may be implemented
as a regular shell built-in. It gives a list of utilities which
are usually implemented that way (and some of them can only
be implemented as built-ins, like "alias"):

alias
bg
cd
command
false
fc
fg
getopts
jobs
kill
newgrp
pwd
read
true
umask
unalias
wait


http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
Shell Command Language

It says that shell must implement special built-ins. Special built-ins
differ from regular ones by the fact that variable assignments
done on special builtin are *PRESERVED*. That is,

VAR=VAL special_builtin; echo $VAR

should print VAL.

(Another distinction is that an error in special built-in should
abort the shell, but this is not such a critical difference,
and moreover, at least bash's "set" does not follow this rule,
which is even codified in autoconf configure logic now...)

List of special builtins:

. file
: [argument...]
break [n]
continue [n]
eval [argument...]
exec [command [argument...]]
exit [n]
export name[=word]...
export -p
readonly name[=word]...
readonly -p
return [n]
set [-abCefhmnuvx] [-o option] [argument...]
set [+abCefhmnuvx] [+o option] [argument...]
set -- [argument...]
set -o
set +o
shift [n]
times
trap n [condition...]
trap [action condition...]
unset [-fv] name...

In practice, no one uses this obscure feature - none of these builtins
gives any special reasons to play such dirty tricks.

However. This section also says that *function invocation* should act
similar to special built-in. That is, variable assignments
done on function invocation should be preserved after function invocation.

This is significant: it is not unthinkable to want to run a function
with some variables set to special values. But because of the above,
it does not work: variable will "leak" out of the function.