On Wed, Oct 30, 2024 at 09:16:36PM +0100, Gioele Barabucci wrote:
> On 30/10/24 13:50, Lionel Élie Mamane wrote:

>>>A fix for this issue is included in 5.2.32-1+b2.

>> I installed 5.2.32-1+b2 and still reproduced exactly the behaviour you
>> describe.

> I just double checked and this issue does not seem reproducible in unstable.

> Setup:

>     $ dpkg -l bash | grep bash
>     ii  bash    5.2.32-1+b2  amd64   GNU Bourne Again SHell
>     $ echo $BASH_VERSION
>     5.2.32(1)-release
>     $ complete -p # no output, bash-completion is not installed
>     $ cd $(mktemp -d)
>     $ touch 'a$b' 'a$c'
>     $ ls
>     'a$b'  'a$c'
>     $ b=GOTYA

> Tests:

>     $ ls <TAB>
>     $ ls a$
>     $ ls a$<TAB><TAB>
>     a$b a$c
>     $ ls a$b<TAB>

That last "<TAB>" is not part of my reproduction steps. There lies the
misunderstanding. The '$' should have already been escaped by the
first <TAB>. Adding that last <TAB> to get a correct command line is
just working around the issue.

>     $ ls a\$b<ENTER>
>     'a$b'

> b is never expanded to GOTYA.

>> The report was not about "*<TAB>" but about "<TAB>*".

> Sorry, I misread that line.

> Nevertheless this issue does not seem to affect the version of bash in
> unstable:

>     $ ls
>     'a$b'  'a$c'
>     $ ls <TAB>
>     $ ls a$
>     $ ls a$*<TAB>
>     # nothing happens
>     $ ls a$*<TAB><TAB>
>     a$b  a$c
>     $ ls a$*

What you show is a reproduction of the issue I report. The '$'
inserted into the command line by the first <TAB> is not escaped.

>>>> $ echo a$b

>>>> then pressing <tab> should NOT escape the '$' since that is not what
>>>> was meant.

>>> Why shouldn't it be escaped?

>> The user requested that the second word of the command line the
>> string "a" followed by the contents of the variable named b. Why
>> would pressing <TAB> change that to the string "a$b"?

> You are mixing different levels: by default, the completion is done by
> readline before the line is evaluated by bash.

> Bash configures readline in the way specified in the manual page under
> READLINE / Completing / complete (TAB):

>> Attempt to perform completion on the text before point.  Bash
>> attempts completion treating the text as a variable (if the text
>> begins with $), username (if the text begins with ~), hostname (if
>> the text begins with @), or command (including aliases and
>> functions) in turn.  If none of these produces a match, filename
>> completion is attempted.

> In this case the text does not start with $, so the default
> completion (filename completion) is attempted by readline.

The string "a$b" (without the double quotes) is not, on the command
line, a prefix for entering the file name "a$b". So there is no reason
for filename completion to match that to the file name "a$b".

On the command line, a valid prefix for the filename "a$b" would be
"a" or "a\$" or "a\$b", and those can/should be auto completed to
"a\$b". But not "a$", nor "a$b".

If you see filename auto completion as a function from strings to
strings, what is the specification of its input and of its output? Is
its input quoted strings or unquoted strings? Is its output quoted
strings or unquoted strings? Fundamentally, the issue is that there is
no stable answer to these questions, it is sometimes the one,
sometimes the other, sometimes a weird mix.

IMO the only sane choice is to both consume quoted strings and produce
quoted strings.

A few examples showing different behaviours:

$ touch 'a$' 'a$bb'
$ ls <TAB>
$ ls a\$
# now it produced a quoted string
$ ls a\$b<TAB>
$ ls a\$bb
# now it consumed a quoted string and produced a quoted string

$ touch 'a$b' 'a$c'
$ ls <TAB>
$ ls a$
# now it produced an UNquoted string
$ ls a$b<TAB>
$ ls a\$b
# now it consumed an UNquoted string and produced a quoted string

$ touch 'a$bc' 'a$bb'
$ ls a$<TAB>
$ ls a$b
# now it consumed an UNquoted string and produced an UNquoted string

$ touch 'a$' 'a$$'
$ ls <TAB>
$ ls a\$
# now it produced an quoted string
$ ls a\$$<TAB>
$ ls a\$\$
# now it did... I don't know what; a weird mix

$ touch 'a$$' 'a\$$'
$ ls a$<TAB>
$ ls a\$\$
# now it consumed an UNquoted string and produced a quoted string
$ ls a\$<TAB>
$ ls a\$\$
# now it consumed a quoted string and produced a quoted string
# if it consumes UNquoted strings, it should have matched the
# filename a\$ and produced the quoted string a\\\$\$
# if it consumes quoted strings, it should have matched the
# filename a$$ and produced the quoted string a\$\$ (as it did)
# but it sometimes does the one, and sometimes the other
# it is just utterly incoherent



And to add to the incoherence, filename completion behaves differently
in respect of other characters.  Compare with the treatment of the
characters ":", "!", "(" and "&" to the one of '$' being discussed
above..

$ touch 'a(b' 'a(c'
$ ls <TAB>
# gives
$ ls a\(
# properly escaped! that is correct!
# and different from what happens with "$"
# delete the command line, and start a new one:
$ ls a(<TAB>
# no match! this is correct!
# and different from what happens with "$"
$ ls a(<TAB><TAB>
# no match! this is correct!
# and different from what happens with "$"

$ rm *
$ touch 'a!b' 'a!c'
$ ls <TAB>
# gives
$ ls a\!
# properly escaped! that is correct!
# and different from what happens with "$"
# delete the command line, and start a new one:
$ ls a!<TAB>
# the result is:
$ ls a\!<TAB>
# this is different than what happens with "("

$ rm *
$ touch 'a:b' 'a:c'
$ ls <TAB>
# gives
$ ls a\:
# this is escaped even though it strictly didn't have to be
# but that is not incorrect, acceptable
# again, different from what happens with "$"
# delete the command line, and start a new one:
$ ls a:<TAB>
# nothing happens, OK, there are two matches,
$ ls a:<TAB><TAB>
# no match! this is NOT correct. There are two matches,
# a:b and a:c

$ rm *
$ touch 'a&b' 'a&c'
$ ls <TAB>
# gives
$ ls a\&
# properly escaped! that is correct!
# and different from what happens with "$"
# again, different from what happens with "$"
# delete the command line, and start a new one:
$ ls a&<TAB>
# nothing happens, that is different from what
# happens with "$" and IMO the correct behaviour
$ ls a&<TAB><TAB>
# thousands of matches, because it is not filename completion
# that is happening but command completion


Do you see the complete incoherence of it all?


--
Lionel

Reply via email to