[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Removing a function's function attribute makes `declare` not know it's a
From: |
Great Big Dot |
Subject: |
Removing a function's function attribute makes `declare` not know it's a function (kind of) |
Date: |
Wed, 21 Nov 2018 23:02:16 -0500 |
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu'
-DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -D_FORTIFY_SOURCE=2
-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt
-DDEFAULT_PATH_VALUE='/usr/local/sbin:/usr/local/bin:/usr/bin'
-DSTANDARD_UTILS_PATH='/usr/bin' -DSYS_BASHRC='/etc/bash.bashrc'
-DSYS_BASH_LOGOUT='/etc/bash.bash_logout' -DNON_INTERACTIVE_LOGIN_SHELLS
-Wno-parentheses -Wno-format-security
uname output: Linux ArchBox0 4.19.2-arch1-1-ARCH #1 SMP PREEMPT Tue Nov 13
21:16:19 UTC 2018 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu
Bash Version: 4.4
Patch Level: 23
Release Status: release
Description:
The manual's section on `declare` (aka `typeset`) states that you can
negate any attribute except for "-r" and "-a" by replacing "-" with "+".
Aside from the fact that this appears to mistakenly leave out associative
arrays ("-A"), this leaves one to wonder what happens if you try to negate
the function attribute. At first glance, this seems impossible, since a
(non-option) argument to `declare` is assumed to be a variable, and only
gets considered a function if you include the "-f" (or "-F") option. But,
if you include *both* "-f" and "+f", something unusual happens. First the
setup and demonstration of `declare`'s usual behavior:
$ func () { echo 'hello world'; }
$ declare -p -- func
bash: declare: func: not found
$ declare -pF -- func
declare -f func
$ declare -pf -- func
func ()
{
echo 'hello world'
}
If we try to remove func's function attribute by just saying "declare +f --
func", `declare` (as usual) assumes we mean the *variable *"func", and
nothing of interest happens. It's equivalent to "declare -- func". But what
if we include "-f" to state we're talking about functions and not
variables, yet include "+f" to try to turn it off?
$ declare -f +f -- func # Expectation: Error message or no-op.
$ func #
hello world # So nothing changed, right? Wrong.
$ declare -p -- func #
bash: declare: func: not found # Again as expected. But...
$ declare -pF -- func #
declare -- func # The "-f" attribute is missing.
Weird...
$ declare -pf -- func #
declare -- func=" " # A tab character? What the heck??
Where did that come from?
Make no mistake, the function is still a function. Executing it works the
same as before, and attempting to expand it as a parameter fails just as
before. In almost all respects, the line `declare -f +f -- func` does
nothing. Yet `declare` has been tricked into an inconsistent view of the
world! Namely, it appears to believe the following things simultaneously:
*1.* There is no variable named "func".
*2.* There is a function named "func".
*3.* This function does NOT have the "-f" attribute. (???)
*4.* This function has a variable definition, not a function
definition. (???)
*5.* The value of this variable definition is a single tab character.
(???????)
Again, `declare`'s vision of the world appears to have no basis in reality.
In particular, expanding "$func" does not yield a tab. Neither the order
nor the case of the "f"-options on the problematic line appear to have any
affect.
Few more random observations:
$ declare -F -- func #
func # Same as normal.
$ declare -f -- func #
func () # }
{ # } Same as normal again.
echo 'hello world' # } Has `declare` regained sanity?
(Spoiler: no)
} # }
# (In the below, irrelevant lines have been removed.)
$ declare #
func # I'm not sure if this is ever a legitimate
output line for a bare `declare`.
$ declare -f # Nothing. In particular, different from
`declare -f -- func`.
$ declare -F # Again nothing, again different from
`declare -F -- func`.
$ declare -fp #
declare -- func=" " # Identical wrong answer as `declare -fp --
func`.
$ declare -Fp #
declare -- func # Ditto.
So, we can add these two to the list of things `declare` believes about
`func`.
*6.* The function `func` has a function definition.
*7.* The function (possibly variable?) named "func" exists, but has no
definition. (???)
*8.* There is no function named "func". (???)
What is going on here?
Repeat-By:
$ func () { echo 'hello, world'; } # Setup.
$ declare -f +f -- func # The problem.
$ declare -pf -- func #
declare -- func=" " # Now `declare` believes
nonsensical things like this.
Fix:
N/A. This is just an edge case that would never actually be used. If
anything, this is the expected behavior:
expected () { printf -- 'bash: declare: %s: inconsistent flags or
something.' "$1" 1>&2; return 1; }
So, just replace any occurrences of the problematic command with calls to
the above, and you're all set! ;)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Removing a function's function attribute makes `declare` not know it's a function (kind of),
Great Big Dot <=