scop / bash-completion

Programmable completion functions for bash
GNU General Public License v2.0
2.8k stars 376 forks source link

fix: source files using absolute paths for absolute BASH_SOURCE #1221

Open akinomyoga opened 2 weeks ago

akinomyoga commented 2 weeks ago

Depending on the setup, we source the completion files with relative paths. This causes a problem when a completion script uses BASH_SOURCE to specify the helper script after the current working directory is changed. For example, with the following steps, the problem happens:

$ bash --norc
$ source bash_completion
$ make [TAB]
$ cd testdir
$ make [TAB]awk: fatal: cannot open source file `./completions/../helpers/make-extract-targets.awk' for reading: No such file or directory

This is because _comp_cmd_make__extract_targets (called by _comp_cmd_make) uses BASH_SOURCE to identify the location of the helper script, but BASH_SOURCE contains a relative path from the directory where the completion file is first sourced.

$ complete -p make
complete -F _comp_cmd_make make
$ type _comp_cmd_make__extract_targets
_comp_cmd_make__extract_targets is a function
_comp_cmd_make__extract_targets ()
{
    local mode=$1;
    local -x prefix=$2;
    local -x prefix_replace=$prefix;
    [[ $mode == -d && $prefix == */* ]] && prefix_replace=${prefix##*/};
    _comp_awk -f "${BASH_SOURCE[0]%/*}/../helpers/make-extract-targets.awk"
}
$ shopt -s extdebug
$ declare -F _comp_cmd_make__extract_targets
_comp_cmd_make__extract_targets 8 ./completions/make

Full processing of .. in _comp_abspath

In the second commit 67e98c68d, I modified _comp_abspath to properly handle ... In the original implementation of _comp_abspath, we just removed the beginning ../ and .. in the middle path segments were left. In this PR, I changed _comp_abspath to fully resolve ... However, was there a reason to just remove ..? I initially thought it might be intended to prevent directory traversing, but it didn't work for that purpose because the middle .. segments are anyway left.

Note

In the following place, I replaced . with the path to the directory containing the file bash_completion, which is determined on the initialization. This aligns with the behavior described in the code comment.

https://github.com/scop/bash-completion/blob/762f410ac2712cf2a1402d6e4bb046a580111fba/bash_completion#L3175-L3184

This means that we have been sourcing the file located in the completion in the actual current directory ./completions/xxx, but this change will remove that behavior.