bash-completion icon indicating copy to clipboard operation
bash-completion copied to clipboard

new occasions of unbound variables

Open calestyo opened this issue 3 years ago • 6 comments

Describe the bug

There are some new occasions of unbound variables, which AFAIU, #44 are now considered bugs.

To reproduce

Invoke "set -u" before invoking bash-completion in .bashrc. Launching a new shell, gives:

bash: filenames: unbound variable
bash: filenames: unbound variable
bash: filenames: unbound variable

Versions (please complete the following information)

  • [ ] Operating system name/distribution and version: Debian sid
  • [ ] bash version, echo "$BASH_VERSION": 5.1.8(1)-release
  • [ ] bash-completion version, (IFS=.; echo "${BASH_COMPLETION_VERSINFO[*]}"): 2.11

calestyo avatar May 13 '21 18:05 calestyo

Thanks for the report. Please follow instructions in the bug report template -- this does not happen for me nor in CI, load time debug trace is needed to diagnose further.

I'm guessing that the trace will reveal that the errors come from completions not included with bash-completion but some 3rd party ones, per the above, and because there is no variable named filenames in the bash-completion source tree that I can see.

scop avatar May 14 '21 19:05 scop

Indeed you're right.

I was just looking at the occurrence of filenames in /usr/share/bash-completion/bash_completion and once I've found it, didn't think about the possibility of 3rd party completions.

Reported the issues at their respective upstreams: [0] [1]

Sorry for the noise

Cheers, Chris.

calestyo avatar May 14 '21 20:05 calestyo

Hey again.

This time I might have found a real occasion ;-)

If I have set -u and a command like: find ../new/ -type f -printf '%f\n' | while IFS='' read -r FILENAME; do printf 'ln -s /dev/nu %q\n' "${FILENAME}" ; done | sh now when I go to the /dev/nu and complete it with tab to /dev/null I get: ../new/ -type f -printf '%f\n' | while IFS='' read -r FILENAME; do printf 'ln -s /dev/nubash: COMP_WORDS[i]: unbound variable

This seems to happen in:

+ offset=1
+ (( i = 1 ))
+ (( i <= COMP_CWORD ))
+ [[ printf != -* ]]
+ offset=1
+ break
+ _command_offset 1
+ local word_offset=1 i j
+ (( i = 0 ))
+ (( i < word_offset ))
+ (( j = 0 ))
+ (( j <= 55 ))
+ [[ do printf 'ln -s /dev/n %q\n' "${FILENAME}" ; done | sh == \d\o* ]]
+ break
+ COMP_LINE=' printf '\''ln -s /dev/n %q\n'\'' "${FILENAME}" ; done | sh'
+ (( COMP_POINT -= 2 ))
+ (( i++ ))
+ (( i < word_offset ))
+ (( i = 0 ))
+ (( i <= COMP_CWORD - word_offset ))
+ COMP_WORDS[i]=printf
+ (( i++ ))
+ (( i <= COMP_CWORD - word_offset ))
+ COMP_WORDS[i]=''\''ln -s /dev/n %q\n'\'''
+ (( i++ ))
+ (( i <= COMP_CWORD - word_offset ))
+ (( i ))
+ (( i <= COMP_CWORD ))
+ unset 'COMP_WORDS[i]'
+ (( i++ ))
+ (( i <= COMP_CWORD ))
+ (( COMP_CWORD -= word_offset ))
+ COMPREPLY=()
+ local cur
+ _get_comp_words_by_ref cur
+ local exclude flag i OPTIND=1
+ words=()
+ local cur cword words
+ upargs=()
+ upvars=()
+ local upargs upvars vcur vcword vprev vwords
+ getopts c:i:n:p:w: flag cur
+ [[ 1 -ge 1 ]]
+ case ${!OPTIND} in
+ vcur=cur
+ (( OPTIND += 1 ))
+ [[ 1 -ge 2 ]]
+ __get_cword_at_cursor_by_ref '' words cword cur
+ words=()
+ local cword words
+ __reassemble_comp_words_by_ref '' words cword
+ local exclude i j line ref
+ [[ -n '' ]]
+ printf -v cword %s 1
+ [[ -v exclude ]]
+ for i in "${!COMP_WORDS[@]}"
+ printf -v 'words[i]' %s printf
+ for i in "${!COMP_WORDS[@]}"
+ printf -v 'words[i]' %s ''\''ln -s /dev/n %q\n'\'''
+ for i in "${!COMP_WORDS[@]}"
+ printf -v 'words[i]' %s '"${FILENAME}"'
+ for i in "${!COMP_WORDS[@]}"
+ printf -v 'words[i]' %s ';'
+ for i in "${!COMP_WORDS[@]}"
+ printf -v 'words[i]' %s done
+ for i in "${!COMP_WORDS[@]}"
+ printf -v 'words[i]' %s '|'
+ for i in "${!COMP_WORDS[@]}"
+ printf -v 'words[i]' %s sh
+ local i cur= index=21 'lead= printf '\''ln -s /dev/n'
+ [[ 21 -gt 0 ]]
+ [[ -n  printf 'ln -s /dev/n ]]
+ [[ -n printf'ln-s/dev/n ]]
+ cur=' printf '\''ln -s /dev/n %q\n'\'' "${FILENAME}" ; done | sh'
+ (( i = 0 ))
+ (( i <= cword ))
+ [[ 53 -ge 6 ]]
+ [[  print != \p\r\i\n\t\f ]]
+ cur='printf '\''ln -s /dev/n %q\n'\'' "${FILENAME}" ; done | sh'
+ (( index > 0 ))
+ (( index-- ))
+ [[ 52 -ge 6 ]]
+ [[ printf != \p\r\i\n\t\f ]]
+ (( i < cword ))
+ local old_size=52
+ cur=' '\''ln -s /dev/n %q\n'\'' "${FILENAME}" ; done | sh'
+ local new_size=46
+ (( index -= old_size - new_size ))
+ (( ++i ))
+ (( i <= cword ))
+ [[ 46 -ge 19 ]]
+ [[  'ln -s /dev/n %q\n != \'\l\n\ \-\s\ \/\d\e\v\/\n\ \%\q\\\n\' ]]
+ cur=''\''ln -s /dev/n %q\n'\'' "${FILENAME}" ; done | sh'
+ (( index > 0 ))
+ (( index-- ))
+ [[ 45 -ge 19 ]]
+ [[ 'ln -s /dev/n %q\n' != \'\l\n\ \-\s\ \/\d\e\v\/\n\ \%\q\\\n\' ]]
+ (( i < cword ))
+ (( ++i ))
+ (( i <= cword ))
+ [[ -n 'ln -s /dev/n %q\n' "${FILENAME}" ; done | sh ]]
+ [[ ! -n 'ln-s/dev/n%q\n'"${FILENAME}";done|sh ]]
+ (( index < 0 ))
+ local words cword cur
+ _upvars -a7 words printf ''\''ln -s /dev/n %q\n'\''' '"${FILENAME}"' ';' done '|' sh -v cword 1 -v cur ''\''ln -s /dev/n'
+ (( 15 ))
+ (( 15 ))
+ case $1 in
+ [[ -n 7 ]]
+ printf %d 7
+ [[ -n words ]]
+ unset -v words
+ eval 'words=("${@:3:7}")'
words=("${@:3:7}")
++ words=("${@:3:7}")
+ shift 9
+ (( 6 ))
+ case $1 in
+ [[ -n cword ]]
+ unset -v cword
+ eval 'cword="$3"'
cword="$3"
++ cword=1
+ shift 3
+ (( 3 ))
+ case $1 in
+ [[ -n cur ]]
+ unset -v cur
+ eval 'cur="$3"'
cur="$3"
++ cur=''\''ln -s /dev/n'
+ shift 3
+ (( 0 ))
+ [[ -v vcur ]]
+ upvars+=("$vcur")
+ upargs+=(-v $vcur "$cur")
+ [[ -v vcword ]]
+ [[ -v vprev ]]
+ [[ -v vwords ]]
+ (( 1 ))
+ local cur
+ _upvars -v cur ''\''ln -s /dev/n'
+ (( 3 ))
+ (( 3 ))
+ case $1 in
+ [[ -n cur ]]
+ unset -v cur
+ eval 'cur="$3"'
cur="$3"
++ cur=''\''ln -s /dev/n'
+ shift 3
+ (( 0 ))
+ (( COMP_CWORD == 0 ))
+ local cmd=printf compcmd=printf
++ complete -p printf
+ local 'cspec=complete -F _minimal printf'
+ [[ ! -n complete -F _minimal printf ]]
+ [[ ! -n complete -F _minimal printf ]]
+ [[ -n complete -F _minimal printf ]]
+ [[ _minimal printf != \c\o\m\p\l\e\t\e\ \-\F\ \_\m\i\n\i\m\a\l\ \p\r\i\n\t\f ]]
+ local 'func=_minimal printf'
+ func=_minimal
+ (( 7 >= 2 ))
+ _minimal printf sh '|'
+ local cur prev words cword split
+ _init_completion -s
+ local exclude= flag outx errx inx OPTIND=1
+ getopts n:e:o:i:s flag -s
+ case $flag in
+ split=false
+ exclude+==
+ getopts n:e:o:i:s flag -s
+ COMPREPLY=()
+ local 'redir=@(?([0-9])<|?([0-9&])>?(>)|>&)'
+ _get_comp_words_by_ref -n '=<>&' cur prev words cword
+ local exclude flag i OPTIND=1
+ words=()
+ local cur cword words
+ upargs=()
+ upvars=()
+ local upargs upvars vcur vcword vprev vwords
+ getopts c:i:n:p:w: flag -n '=<>&' cur prev words cword
+ case $flag in
+ exclude='=<>&'
+ getopts c:i:n:p:w: flag -n '=<>&' cur prev words cword
+ [[ 6 -ge 3 ]]
+ case ${!OPTIND} in
+ vcur=cur
+ (( OPTIND += 1 ))
+ [[ 6 -ge 4 ]]
+ case ${!OPTIND} in
+ vprev=prev
+ (( OPTIND += 1 ))
+ [[ 6 -ge 5 ]]
+ case ${!OPTIND} in
+ vwords=words
+ (( OPTIND += 1 ))
+ [[ 6 -ge 6 ]]
+ case ${!OPTIND} in
+ vcword=cword
+ (( OPTIND += 1 ))
+ [[ 6 -ge 7 ]]
+ __get_cword_at_cursor_by_ref '=<>&' words cword cur
+ words=()
+ local cword words
+ __reassemble_comp_words_by_ref '=<>&' words cword
+ local exclude i j line ref
+ [[ -n =<>& ]]
+ exclude='[=<>&]'
+ printf -v cword %s 1
+ [[ -v exclude ]]
+ line=' printf '\''ln -s /dev/n %q\n'\'' "${FILENAME}" ; done | sh'
+ (( i = 0, j = 0 ))
+ (( i < 7 ))
+ [[ 0 -gt 0 ]]
+ ref='words[0]'
+ printf -v 'words[0]' %s printf
+ line=' '\''ln -s /dev/n %q\n'\'' "${FILENAME}" ; done | sh'
+ (( i == COMP_CWORD ))
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 1 -gt 0 ]]
+ [[ 'ln -s /dev/n %q\n' == +([=<>&]) ]]
+ ref='words[1]'
+ printf -v 'words[1]' %s ''\''ln -s /dev/n %q\n'\'''
+ line=' "${FILENAME}" ; done | sh'
+ (( i == COMP_CWORD ))
+ printf -v cword %s 1
+ (( i++, j++ ))
+ (( i < 7 ))
+ [[ 2 -gt 0 ]]
bash: COMP_WORDS[i]: unbound variable

Thanks, Chris.

calestyo avatar May 19 '21 17:05 calestyo

Yup, reproduced, thanks.

scop avatar May 19 '21 18:05 scop

I think I might have found another case:

scp someKnownHostname:fo<TAB>
bash: $1: unbound variable

also fails for me, when I try to complete the remote pathnames.

calestyo avatar Jun 23 '21 01:06 calestyo

I can't seem to be able to reproduce that one. Please file a new issue about that and complete the info requested in it so we can debug that one further.

scop avatar Jun 28 '21 11:06 scop