bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Single quotes are lost from v="$(cmd $'A\tB')"


From: mike . stroyan
Subject: Single quotes are lost from v="$(cmd $'A\tB')"
Date: Mon, 09 Jan 2006 06:21:07 -0700

Configuration Information [Automatically generated, do not change]:
Machine: ia64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='ia64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='ia64-unknown-linux-gnu' 
-DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H   -I.  -I../bash -I../bash/include -I../bash/lib   -g 
-O2
uname output: Linux hpstryn3 2.6.12.3 #1 Fri Jul 29 12:58:27 MDT 2005 ia64 
GNU/Linux
Machine Type: ia64-unknown-linux-gnu

Bash Version: 3.1
Patch Level: 0
Release Status: release

Description:
        Single quotes are lost inside of command substitution inside double 
quotes.

  The difference in known_hosts() function actually comes from a
side effect of an intentional change to bash.  A quoting change that
first appeared in bash-3.1-beta1 has caused a new problem with quoting.
The description for the change was-

t.  Fixed a bug that caused the expanded value of a $'...' string to be
    incorrectly re-quoted if it occurred within a double-quoted ${...}
    parameter expansion. 

  The 'fix' in bash-3.1/bash/parse.y checks for double quoting and
suppresses requoting of $'' single quotes.

                  if ((rflags & P_DQUOTE) == 0)
                      {
                        nestret = sh_single_quote (ttrans);
                        free (ttrans);
                        nestlen = strlen (nestret);
                      }
                    else
                      {
                        nestret = ttrans;
                        nestlen = ttranslen;
                      }

  But that test is fooled when double quoting is used around command
substitution.  The single quotes are dropped even though the string
will be evaluated first by the command substitution inside of the double
quotes.  That breaks the _known_hosts() function for command completion
code in debian's /etc/bash_completion.  The loss of quoting breaks up
input to sed that was intended to be a single argument.


Repeat-By:

Here is an example showing first the intended change to ${} and
then the unintended change to $().

$ cat quote_bugs
function args
 for a in "$@";do echo "'$a'";done
unset mytab
echo "${mytab:-$'\t'}" | od -c
echo "$( args $'A\tB' )"
$ bash_source/bash-3.0/build-bash/bash -v quote_bugs
function args
 for a in "$@";do echo "'$a'";done
unset mytab
echo "${mytab:-$'\t'}" | od -c
0000000   '  \t   '  \n
0000004
echo "$( args $'A\tB' )"
 args 'A        B'
'A      B'
$ bash_source/bash-3.1/build-bash/bash -v quote_bugs
function args
 for a in "$@";do echo "'$a'";done
unset mytab
echo "${mytab:-$'\t'}" | od -c
0000000  \t  \n
0000002
echo "$( args $'A\tB' )"
 args A B
'A'
'B'
$


Fix:

The problem can be avoided by removing the P_DQUOTE bit from
rflags when calling parse_matched_pair for $() expansion.
Here is a patch.

--- bash/parse.y~       2006-01-07 16:11:12.000000000 -0700
+++ bash/parse.y        2006-01-07 16:12:40.000000000 -0700
@@ -2906,8 +2906,8 @@
        {
          if (open == ch)       /* undo previous increment */
            count--;
-         if (ch == '(')                /* ) */
-           nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags);
+         if (ch == '(')                /* ) */  /* disable P_DQUOTE for $() */
+           nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & 
~P_DQUOTE);
          else if (ch == '{')           /* } */
            nestret = parse_matched_pair (0, '{', '}', &nestlen, 
P_FIRSTCLOSE|rflags);
          else if (ch == '[')           /* ] */


-- 
Mike Stroyan, mike.stroyan@hp.com




reply via email to

[Prev in Thread] Current Thread [Next in Thread]