Функция локальная только для чтения и глобальная переменная только для чтения с тем же именем - PullRequest
14 голосов
/ 18 февраля 2011

Я получаю удивительное поведение, когда у меня есть локальная переменная только для чтения и глобальная переменная только для чтения с тем же именем.

Когда опция только для чтения удалена из глобального объявления. * Т.е. 1003 *

declare -r var="main"

изменено на:

declare var="main"

Я получаю ожидаемое поведение. Я читал справочную страницу bash, но не могу найти объяснения этому поведению. Не могли бы вы указать мне раздел (ы) руководства, объясняющий проблему?

Я думаю, что это проблема подобного типа, чем Как лексическая область видимости поддерживается в разных языках оболочки? , но более конкретно.

подробности:

$ 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

Я привязан к этой конкретной версии Bash.

$ ./readonly_variable.sh
BASH_VERSION = 3.2.25(1)-release
./readonly_variable.sh: line 24: local: var: readonly variable
main
main
$

1 Ответ

12 голосов
/ 18 февраля 2011

На самом деле, локальное копирование глобальных переменных только для чтения явно запрещено по соображениям безопасности, как описано в исходном коде bash (в variables.c:make_local_variable):

Проверка на уровне контекста old_varзапрещает локальные копии глобальных переменных только для чтения (поскольку «Я» считает, что это может быть дырой в безопасности).

(где «Я» - это не я, я просто цитирую)

/* 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...