bug-bash
[Top][All Lists]
Advanced

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

Re: test '-v' - associative vs. normal array discrepancy - a bug ?


From: konsolebox
Subject: Re: test '-v' - associative vs. normal array discrepancy - a bug ?
Date: Fri, 21 Nov 2014 10:45:53 +0800

On Fri, Nov 21, 2014 at 6:35 AM, Greg Wooledge <address@hidden> wrote:
> blackbox() { declare -n arg=$1; printf '%s\n' "$arg"; }
>
> It works fine, MOST of the time:
>
> imadev:~$ blackbox LOGNAME
> wooledg
>
> But if the caller doesn't know that the word "arg" is magical, behold:
>
> imadev:~$ blackbox arg
> bash: warning: arg: circular name reference

I believe naming conflicts can easily be avoided by having naming rules.  For
example, if a function that's meant to be shared refers to a variable, every
variable in it should start with two underscores e.g. __a, __b, __r.  These
forms of variables must be declared local and are only allowed to be used
inside the function.  They are not allowed to be used by other functions or
passed by reference to another.  If a referring function must call another
referring function, the local variable that it should pass should be prefixed
with its name e.g. my_function__var.  With this I don't think there's a way
for variables to be in conflict with each other.  With respect to functions
needing to have recursive calls, it would depend but I believe that would be
another different issue about the functions' design.

To add, it's not only by namerefs that a function can refer a variable.  The
reference can also just stay in a positional parameter.

Some functions can just save the results to a variable that's practically
accepted as a common variable for storing results so if a function does not
really have to refer to the value of an outside variable directly, it probably
can just consider accepting arguments instead.

> No matter how cleverly you name your nameref, there's a CHANCE that the
> caller will try to use that same name.

Yes there's still a chance, but I don't think that's enough reason to prevent
you from creating shared functions.

> Once you see the error message above, you should understand that bash's
> namerefs don't actually point to a variable in the caller's scope.
> They don't work ANYTHING like ksh's nameref, or Tcl's upvar.  They're
> really just eval in disguise.  As such, they inherit all the problems of
> eval.  For example, arbitrary undesired code execution:
>
> imadev:~$ blackbox 'a[b=$(date)]'
> bash: b=Thu Nov 20 17:33:35 EST 2014: syntax error in expression (error token 
> is "Nov 20 17:33:35 EST 2014")
>
> I describe this in a bit more detail at 
> http://mywiki.wooledge.org/BashFAQ/048#The_problem_with_bash.27s_name_references

For this, like I said there are two things that can be done:

1) The caller should make sure it doesn't send dangerous or invalid arguments
   to the function.

2) Optionally the shared function can check the argument if it's a valid
   variable name before assigning it to a reference, whether it's by declare -n
   or as an ordinary assignment for a variable reference.  This can also solve
   calls that are interactive and not script-based.

I believe this is enough to fix that.

shopt -s extglob  ## Use extglob, or use regex depending on target version of
                  ## Bash.  Extended globbing is also enabled by default in 4.1
                  ## and so should also be considered.

blackbox() {
    [[ $1 == [[:alpha:]_]*([[:alnum:]_]) ]] || return 1  ## Or use
print_error_message_and_exit().
    declare -n arg=$1; printf '%s\n' "$arg"  ## Even just using ${!1}
would work.
}

And I don't think there would be any practical situation where the shared
function in an interactive session should always check if the argument passed
to it is valid since if the user can do "blackbox 'a[b=$(something_evil)]'",
then why would he not just run something_evil directly anyway.  If it's
anything other than that then it's probably the scripts being called or is
running the automation that should be questioned.

Also consider that: Not all functions are given with difficult problems.
Some actually can just have simpler tasks e.g. they don't have to care if the
variable is of a different type like an associative array or not.  Assigning
and expanding a single value to and from a variable declared with any flag is
virtually just the same.

So again, creating shared functions is doable and doable in the proper
non-hacky way.  Saying that it can't be done or should never be done for me is
just not right.


Cheers,
konsolebox



reply via email to

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