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.)