Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function local read-only vs. global read-only variable with the same name

Tags:

scope

bash

I get a suprising behaviour when I have a function local read-only variable and global read-only variable with the same name.

When read-only option is removed from global declaration. I.e.

declare -r var="main"

is changed to:

declare var="main"

I get the expected behaviour. I've been reading bash man page but I can't find an explanation to this behaviour. Could you please point me to the section(s) of the manual explaining the issue ?

I think this is a similar kind of issue than How does lexical scoping supported in different shell languages? but more specific.

Details:

$ cat readonly_variable.sh 
#!/bin/bash

# expected output:
#
# BASH_VERSION = 3.2.25(1)-release
# function
# main
#
# but instead getting:
#
# BASH_VERSION = 3.2.25(1)-release
# ./readonly_variable.sh: line 6: local: var: readonly variable
# main
# main
#
# when read-only option (-r) is removed from global declaration (*), the output
# is expected

set -o nounset

function func {
  local -r var="function"
  echo "$var"
}

declare -r var="main" # (*)

echo BASH_VERSION = $BASH_VERSION
echo $(func)
echo $var

exit 0

I'm stucked to this particular Bash version.

$ ./readonly_variable.sh
BASH_VERSION = 3.2.25(1)-release
./readonly_variable.sh: line 24: local: var: readonly variable
main
main
$
like image 441
user272735 Avatar asked Feb 18 '11 07:02

user272735


People also ask

Can a local variable and a global variable have the same name?

It is usually not a good programming practice to give different variables the same names. If a global and a local variable with the same name are in scope, which means accessible, at the same time, your code can access only the local variable.

Can local variables have the same name?

Although it is usually a bad idea, you can declare a formal parameter or a local variable with the same name as one of the instance variables.

Can we declare same variable in two times globally?

2 Answers. Show activity on this post. In C, multiple global variables are "merged" into one. So you have indeed just one global variable, declared multiple times.

How do I change a read-only variable in Linux?

The shell provides a way to protect variables as read-only by using the readonly command. After a variable is marked read-only, we cannot change the value of the variable. As we can see from the output, we cannot assign to the variable declared as readonly.


1 Answers

Actually, making local copies of readonly global variables is explicitely forbidden for security reasons, as documented in bash source code (in variables.c:make_local_variable):

The test against old_var's context level is to disallow local copies of readonly global variables (since "I" believe that this could be a security hole).

(where "I" is not me, I'm merely quoting)

/* Since this is called only from the local/declare/typeset code, we can
   call builtin_error here without worry (of course, it will also work
   for anything that sets this_command_name).  Variables with the `noassign'
   attribute may not be made local.  The test against old_var's context
   level is to disallow local copies of readonly global variables (since I
   believe that this could be a security hole).  Readonly copies of calling
   function local variables are OK. */
if (old_var && (noassign_p (old_var) ||
   (readonly_p (old_var) && old_var->context == 0)))
{
  if (readonly_p (old_var))
    sh_readonly (name);
  return ((SHELL_VAR *)NULL);
}
like image 186
zarkdav Avatar answered Oct 07 '22 00:10

zarkdav