[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
`complete -p -- <cmd>` doesn't yield reusable input when "-F" is assigne
From: |
Great Big Dot |
Subject: |
`complete -p -- <cmd>` doesn't yield reusable input when "-F" is assigned an invalid identifier |
Date: |
Thu, 24 Jan 2019 12:24:46 -0500 |
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -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.20.0-arch1-1-ARCH #1 SMP PREEMPT Mon Dec 24
03:00:40 UTC 2018 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu
Bash Version: 5.0
Patch Level: 0
Release Status: release
Description:
According to the manual's section on the `complete` builtin:
> "If the -p option is supplied, or if no options are supplied,
existing completion specifications are printed in a way that allows
them to be reused as input."
Unfortunately, there is at least one edge cases that, despite being
invalid, are considered valid by `complete`, and the proper measures to
deal with it are not taken. Namely:
$ complete -F 'bad func' -- cmd # No error is triggered here...
$ complete -p -- cmd #
=> complete -F bad func cmd # Not quoted!!
The expected behavior ought to be either that the first line yields an
error (e.g., "bash: `'bad func'': not a valid identifier"), or else the
second line's output is properly quoted. In particular, if you treat
the output of `complete -p -- cmd` as valid, sanitized data safe for
input, you can get any result. E.g., running `eval -- "$(complete -p --
cmd)"` in this case would set the completion for both `cmd` and "func"
to the function "bad", which bears little resemblance to what should be
done.
Semicolons and quotes such aren't escaped either, so you can in fact
run arbitrary code if you evaluate it. (Yes, I know that `eval` is
considered unsafe in general for exactly this reason, but the output of
`complete -p` is supposed to be safe for reuse; this ought to be a rare
case when `eval` shouldn't cause problems, no matter what the input.)
The command name itself is also never quoted. E.g.:
$ complete -F func -- 'bad cmd' # Maybe technically a valid command?
$ complete -p -- 'bad cmd' #
=> complete -F func bad cmd # Not quoted!
(For whatever reason, if you set a completion with "-C", *its* argument
is escaped properly.)
This does only occur in the case of invalid identifiers, but no error
is thrown, so it seems like a problem nonetheless. Putting the above
results another way, `complete -p` silently transforms an invalid
command to an entirely different, potentially valid command.
Repeat-By:
$ complete -F 'invalid indentifier' -- cmd
$ complete -p -- cmd
=> complete -F invalid identifier cmd
Fix:
As long as you don't do dumb stuff like setting a completion to a
"function" with an invalid identifier, this problem is irrelevant. If
you don't need to parse the output of complete (e.g., if you can make
an array variable to hold the info or something), it is also
irrelevant.
But if you are using `complete -p` and there is for some reason the
potential for invalid identifiers, I think parsing can actually still
be done accurately, provided you know the name of the command you're
completing. (If you don't have the command name, you can't in general
extract it from the completion, thanks to this bug. E.g., `complete -F
'foo bar' -- baz` and `complete -F foo -- 'bar baz'` both yield
"complete -F foo bar baz".)
Namely: remove the command name and a space from the end of
`complete -p`'s output, then find the first unquoted " -F "; everything
after it is the actual function name. (If any of the other complete
options have problems (which would make it impossible to find the first
"real" " -F "), I haven't found them.)
- `complete -p -- <cmd>` doesn't yield reusable input when "-F" is assigned an invalid identifier,
Great Big Dot <=