[Top][All Lists]

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

Re: Preventing Bash Variable Confusion

From: Robert Elz
Subject: Re: Preventing Bash Variable Confusion
Date: Thu, 30 Jan 2020 01:03:31 +0700

    Date:        Wed, 29 Jan 2020 09:23:05 -0500
    From:        Greg Wooledge <address@hidden>
    Message-ID:  <address@hidden>

  | As far as functions go, bash allows you to define local variables within
  | a function.  This avoids namespace collisions as long as you're within
  | that function.

It actually doesn't, or not generally - it allows the function to avoid
namespace collisions with random globals (or other locals) that might exist
up the call stack, but doesn't prevent functions that are called from
trampling all over this function's local vars.

Some variants of ksh apparently make local vars work more like local
vars in C (or other similar languages) and inaccessible outside the
function, but that doesn't really work well for shell, it is useful
to be able to make things like PATH, IFS, ... local in a function,
change their values, and then call other functions which then use
(and can alter) the modified values.

  | Obviously, sh doesn't have this feature,

The POSIX spec doesn't have local vars, but all the shells that are
used very much do, though the details of exactly how they work differ.
If we could get everyone to agree on how they should work, they'd be
in POSIX by now as well.

  | Since the Subject: of this thread includes the word "Bash", it seems
  | likely that the OP is not concerned with portable-sh issues at the
  | moment.

Of course, which is why I suggested using local vars.   One must however
remain aware of the limitations.  Of course if the function in question
calls no other functions, then there is no problem, but knowing that is
true for any function that does any more than variable manipulations
(X=${Y%...} type things, including arithmetic, and which doesn't do everything
in a subshell) is very difficult, and then unless the function writes
"command" (or in bash, perhaps "builtin") before everything that is a
command, then it remains vulnerable.

Consider the proposed trap handling function, copied from another message

        sigint_handler() {
                trap - INT
                kill -INT $$

(which has no vars, and manipulates none, so looks dafe enough) but
then consider

        trap() {
                command trap "$@"
        kill() {
                command kill "$@"

and to make this a little more illustrative, consider that instead
of the above, we have:

        sigint_handler() {
                local My_Var=$$
                trap - INT
                kill -s INT "${My_Var}"

None of this is very likely in practice, but things like it do
occasionally happen.

It could be fixed by

        sigint_handler() {
                command local My_Var=$$
                command trap - INT
                command kill -s INT "${My_Var}"

but when you find someone who actually writes their code like that,
please let me know.


reply via email to

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