[Bash-completion-devel] [bash-completion-Bugs][312741] shopt -s failglob breaks __reassemble_comp_words_by_ref

bash-completion-bugs at alioth.debian.org bash-completion-bugs at alioth.debian.org
Mon Jun 2 14:19:08 UTC 2014


bash-completion-Bugs item #312741 was changed at 2014-06-02 17:19 by Ville Skyttä
You can respond by visiting: 
https://alioth.debian.org/tracker/?func=detail&atid=413095&aid=312741&group_id=100114

>Status: Closed
Priority: 3
Submitted By: Ville Skyttä  (scop-guest)
Assigned to: Nobody (None)
Summary: shopt -s failglob breaks __reassemble_comp_words_by_ref 
Distribution: None
Originally reported in: None
Milestone: None
>Status: Fix Committed
Original bug number: 


Initial Comment:
$ shopt -s failglob
$ ssh <TAB>bash: no match: words[0]=${!ref}${COMP_WORDS[i]}

http://thread.gmane.org/gmane.comp.shells.bash.completion.devel/2546

----------------------------------------------------------------------

>Comment By: Ville Skyttä  (scop-guest)
Date: 2014-06-02 17:19

Message:
It doesn't seem to break anything and fixes a bunch of unit tests with failglob on, so I've committed a slightly modified version of Dams' patch (dropped one no-op cosmetic hunk and another which seems unrelated and broken):
http://anonscm.debian.org/gitweb/?p=bash-completion/bash-completion.git;a=commitdiff;h=732906b25096508fbc5d15d684dea0312ed7fca0

However, there are still some bits to iron out with failglob on. I've filed #314707 to track at least one, I suppose a bunch of others are still lurking there and can be found if running the completion tests with failglob on:
https://alioth.debian.org/tracker/index.php?func=detail&aid=314707&group_id=100114&atid=413095

----------------------------------------------------------------------

Comment By: Dams Nadé (anvil-guest)
Date: 2014-06-02 16:00

Message:
Ville, I use failglob on a daily basis and the (poorly-pasted - sorry about that) patch I've put has been working for a couple of years, now.

Any chance we can see this applied in the git ? If you can still failures after that you can count me in for a troubleshooting/debugging session.

----------------------------------------------------------------------

Comment By: Dams Nadé (anvil-guest)
Date: 2014-02-17 15:03

Message:
I got this patch, here to solve this issue i think :

diff -u --exclude CVS --exclude .svn --exclude .bzr --exclude .pc --exclude test --exclude completions --exclude debian -ub bash-completion-1.3.orig/bash_completion bash-completion-1.3/bash_completion
--- bash-completion-1.3.orig/bash_completion    2013-09-12 16:06:45.000000000 +0200
+++ bash-completion-1.3/bash_completion 2013-09-12 17:25:19.000000000 +0200
@@ -286,7 +286,7 @@
     fi
         
     # Default to cword unchanged
-    eval $3=$COMP_CWORD
+    printf -v "$3" %s "$COMP_CWORD"
     # Are characters excluded which were former included?
     if [[ $exclude ]]; then
         # Yes, list of word completion separators has shrunk;
@@ -296,26 +296,28 @@
             # empty and is word made up of just word separator characters to be
             # excluded?
             while [[ $i -gt 0 && ${COMP_WORDS[$i]} && 
-                ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]} 
+                ${COMP_WORDS[$i]//[^$exclude]} = ${COMP_WORDS[$i]} 
             ]]; do
                 [ $j -ge 2 ] && ((j--))
                 # Append word separator to current word
                 ref="$2[$j]"
-                eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+                printf -v "$ref" %s "${!ref}${COMP_WORDS[i]}"
                 # Indicate new cword
-                [ $i = $COMP_CWORD ] && eval $3=$j
+                [ $i = $COMP_CWORD ] && printf -v "$3" %s "$j"
                 # Indicate next word if available, else end *both* while and for loop
                 (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
             done
             # Append word to current word
             ref="$2[$j]"
-            eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+            printf -v "$ref" %s "${!ref}${COMP_WORDS[i]}"
             # Indicate new cword
-            [[ $i == $COMP_CWORD ]] && eval $3=$j
+            [[ $i == $COMP_CWORD ]] && printf -v "$3" %s "$j"
         done
     else
         # No, list of word completions separators hasn't changed;
-        eval $2=\( \"\${COMP_WORDS[@]}\" \)
+        for i in "${!COMP_WORDS[@]}"; do
+            printf -v "$2[i]" %s "${COMP_WORDS[i]}"
+        done
     fi
 } # __reassemble_comp_words_by_ref()
 
@@ -1481,7 +1483,7 @@
         COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
     done
     for (( i; i <= COMP_CWORD; i++ )); do
-        unset COMP_WORDS[i];
+        unset 'COMP_WORDS[i]'
     done
     COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
 


----------------------------------------------------------------------

Comment By: Dams Nadé (anvil-guest)
Date: 2014-02-17 14:49

Message:
A better eval-free approach would be to simple do

printf -v "$2" %s "${!ref}${COMP_WORDS[i]}"

It's faster and more secure this way, imho.

----------------------------------------------------------------------

Comment By: Ville Skyttä  (scop-guest)
Date: 2014-02-17 14:45

Message:
Unfortunately __reassemble_comp_words_by_ref is not the only thing affected by failglob. At least all _install_xspec ones and ipmitool are, and I don't know of a good recipe how to detect/grep an exhaustive list.

One approach for better-than-nothing coverage is to set "shopt -s failglob" in our test suite's test/config/bashrc and start working on the failures it causes there.

----------------------------------------------------------------------

Comment By: Isaac Jurado (etanol-guest)
Date: 2014-02-17 12:57

Message:
I found this issue too (using 2.0 from Ubuntu Saucy).  There is actually a very simple fix that allows you to have failglob enabled with bash_completion included too.

The trick is to temporarily disable failglob while executing the __reassemble_comp_words_by_ref and then restoring it, in case it was disabled:


--- /usr/share/bash-completion/bash_completion.orig	2014-02-17 11:44:05.879501602 +0100
+++ /usr/share/bash-completion/bash_completion	2014-02-17 11:42:25.967499666 +0100
@@ -237,7 +237,10 @@
 #
 __reassemble_comp_words_by_ref()
 {
-    local exclude i j line ref
+    local exclude i j line ref fgr
+    shopt -pq failglob
+    fgr=$?
+    shopt -u failglob
     # Exclude word separator characters?
     if [[ $1 ]]; then
         # Yes, exclude word separator characters;
@@ -288,6 +291,7 @@
         # No, list of word completions separators hasn't changed;
         eval $2=\( \"\${COMP_WORDS[@]}\" \)
     fi
+    (( $fgr )) || shopt -s failglob
 } # __reassemble_comp_words_by_ref()
 



----------------------------------------------------------------------

Comment By: Ian! D. Allen (idallen-guest)
Date: 2013-08-31 01:28

Message:
In addition to failures under "set -u", using "shopt -s failglob" also
causes errors that make all bash_completion versions (including 2.1)
unusable:

$ env -i bash --login --noprofile --norc
bash-4.2$ shopt -s failglob
bash-4.2$ . /usr/share/bash-completion/bash_completion
bash-4.2$ make <TAB> bash: no match: words[0]=${!ref}${COMP_WORDS[i]}
bash-4.2$ find <TAB> bash: no match: words[0]=${!ref}${COMP_WORDS[i]}
bash-4.2$ mutt <TAB> bash: no match: words[0]=${!ref}${COMP_WORDS[i]}
bash-4.2$ date <TAB> bash: no match: words[0]=${!ref}${COMP_WORDS[i]}
bash-4.2$ echo <TAB> bash: no match: words[0]=${!ref}${COMP_WORDS[i]}
etc.

The code has many errors where characters are not quoted (e.g. bash
array subscripts), so they try to expand as GLOB file names and fail.

As an example, to fix the above, change the lines:

eval $2[$j]=\${!ref}\${COMP_WORDS[i]}

to this:

eval "$ref"='${!ref-}${COMP_WORDS[i]-}'

everywhere (and also fix it so that "set -u" doesn't also make it fail).

----------------------------------------------------------------------

You can respond by visiting: 
https://alioth.debian.org/tracker/?func=detail&atid=413095&aid=312741&group_id=100114



More information about the Bash-completion-devel mailing list