bug-bash
[Top][All Lists]
Advanced

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

Bash-3.2 Official Patch 14


From: Chet Ramey
Subject: Bash-3.2 Official Patch 14
Date: Wed, 21 Mar 2007 11:30:40 -0400

                             BASH PATCH REPORT
                             =================

Bash-Release: 3.2
Patch-ID: bash32-014

Bug-Reported-by: Brett Stahlman <brettstahlman@comcast.net>
Bug-Reference-ID: <000701c72d29$a227e0e0$5ec7cf47@computerroom>
Bug-Reference-URL: 
http://lists.gnu.org/archive/html/bug-bash/2006-12/msg00065.html

Bug-Description:

Bash mishandles word splitting under certain circumstances when IFS is
null (IFS=).  Constructs affected include ${param/pat/sub} and others
when expanding arrays (array[@]).

Patch:

*** ../bash-3.2-patched/array.c Wed Jun  1 16:39:22 2005
--- array.c     Mon Jan 15 22:58:00 2007
***************
*** 121,125 ****
  }
  
- #ifdef INCLUDE_UNUSED
  /*
   * Make and return a new array composed of the elements in array A from
--- 121,124 ----
***************
*** 142,146 ****
                n = array_create_element (element_index(p), element_value(p));
                ADD_BEFORE(a->head, n);
!               mi = element_index(ae);
        }
        a->num_elements = i;
--- 141,145 ----
                n = array_create_element (element_index(p), element_value(p));
                ADD_BEFORE(a->head, n);
!               mi = element_index(n);
        }
        a->num_elements = i;
***************
*** 148,152 ****
        return a;
  }
- #endif
  
  /*
--- 147,150 ----
***************
*** 301,304 ****
--- 299,319 ----
  }
  
+ ARRAY *
+ array_quote_escapes(array)
+ ARRAY *array;
+ {
+       ARRAY_ELEMENT   *a;
+       char    *t;
+ 
+       if (array == 0 || array_head(array) == 0 || array_empty(array))
+               return (ARRAY *)NULL;
+       for (a = element_forw(array->head); a != array->head; a = 
element_forw(a)) {
+               t = quote_escapes (a->value);
+               FREE(a->value);
+               a->value = t;
+       }
+       return array;
+ }
+ 
  /*
   * Return a string whose elements are the members of array A beginning at
***************
*** 312,318 ****
  int   starsub, quoted;
  {
        ARRAY_ELEMENT   *h, *p;
        arrayind_t      i;
!       char            *ifs, sep[2];
  
        p = a ? array_head (a) : 0;
--- 327,334 ----
  int   starsub, quoted;
  {
+       ARRAY           *a2;
        ARRAY_ELEMENT   *h, *p;
        arrayind_t      i;
!       char            *ifs, sep[2], *t;
  
        p = a ? array_head (a) : 0;
***************
*** 337,340 ****
--- 353,363 ----
                ;
  
+       a2 = array_slice(a, h, p);
+ 
+       if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+               array_quote(a2);
+       else
+               array_quote_escapes(a2);
+ 
        if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) {
                ifs = getifs();
***************
*** 344,348 ****
        sep[1] = '\0';
  
!       return (array_to_string_internal (h, p, sep, quoted));
  }
  
--- 367,374 ----
        sep[1] = '\0';
  
!       t = array_to_string (a2, sep, 0);
!       array_dispose(a2);
! 
!       return t;
  }
  
***************
*** 368,372 ****
  
        if (mflags & MATCH_QUOTED)
!               array_quote (a2);
        if (mflags & MATCH_STARSUB) {
                ifs = getifs();
--- 394,400 ----
  
        if (mflags & MATCH_QUOTED)
!               array_quote(a2);
!       else
!               array_quote_escapes(a2);
        if (mflags & MATCH_STARSUB) {
                ifs = getifs();
*** ../bash-3.2-patched/array.h Sun Jun  1 15:50:30 2003
--- array.h     Mon Jan 15 22:35:35 2007
***************
*** 56,59 ****
--- 56,60 ----
  extern int    array_shift_element __P((ARRAY *, char *));
  extern ARRAY  *array_quote __P((ARRAY *));
+ extern ARRAY  *array_quote_escapes __P((ARRAY *));
  
  extern char   *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, 
int));
*** ../bash-3.2-patched/subst.c Fri Mar  2 16:20:50 2007
--- subst.c     Tue Mar  6 11:40:55 2007
***************
*** 1888,1892 ****
--- 1889,1899 ----
  #endif
  
+   /* XXX -- why call quote_list if ifs == 0?  we can get away without doing
+      it now that quote_escapes quotes spaces */
+ #if 0
    tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
+ #else
+   tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ #endif
                ? quote_list (list)
                : list_quote_escapes (list);
***************
*** 2922,2926 ****
  /* Quote escape characters in string s, but no other characters.  This is
     used to protect CTLESC and CTLNUL in variable values from the rest of
!    the word expansion process after the variable is expanded. */
  char *
  quote_escapes (string)
--- 2935,2944 ----
  /* Quote escape characters in string s, but no other characters.  This is
     used to protect CTLESC and CTLNUL in variable values from the rest of
!    the word expansion process after the variable is expanded.  If IFS is
!    null, we quote spaces as well, just in case we split on spaces later
!    (in the case of unquoted $@, we will eventually attempt to split the
!    entire word on spaces).  Corresponding code exists in dequote_escapes.
!    Even if we don't end up splitting on spaces, quoting spaces is not a
!    problem. */
  char *
  quote_escapes (string)
***************
*** 2930,2933 ****
--- 2948,2952 ----
    size_t slen;
    char *result, *send;
+   int quote_spaces;
    DECLARE_MBSTATE; 
  
***************
*** 2935,2938 ****
--- 2954,2958 ----
    send = string + slen;
  
+   quote_spaces = (ifs_value && *ifs_value == 0);
    t = result = (char *)xmalloc ((slen * 2) + 1);
    s = string;
***************
*** 2940,2944 ****
    while (*s)
      {
!       if (*s == CTLESC || *s == CTLNUL)
        *t++ = CTLESC;
        COPY_CHAR_P (t, s, send);
--- 2960,2964 ----
    while (*s)
      {
!       if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
        *t++ = CTLESC;
        COPY_CHAR_P (t, s, send);
***************
*** 2982,2985 ****
--- 3002,3006 ----
    size_t slen;
    char *result, *send;
+   int quote_spaces;
    DECLARE_MBSTATE;
  
***************
*** 2996,3002 ****
      return (strcpy (result, s));
  
    while (*s)
      {
!       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
        {
          s++;
--- 3017,3024 ----
      return (strcpy (result, s));
  
+   quote_spaces = (ifs_value && *ifs_value == 0);
    while (*s)
      {
!       if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces 
&& s[1] == ' ')))
        {
          s++;
***************
*** 4462,4466 ****
        RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, 
DEFAULT_ARRAY_SIZE);
  
!       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == 
CTLNUL)
        istring[istring_index++] = CTLESC;
  
--- 4498,4510 ----
        RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, 
DEFAULT_ARRAY_SIZE);
  
!       /* This is essentially quote_string inline */
!       if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c 
== CTLNUL */)
!       istring[istring_index++] = CTLESC;
!       /* Escape CTLESC and CTLNUL in the output to protect those characters
!        from the rest of the word expansions (word splitting and globbing.)
!        This is essentially quote_escapes inline. */
!       else if (c == CTLESC)
!       istring[istring_index++] = CTLESC;
!       else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
        istring[istring_index++] = CTLESC;
  
***************
*** 5552,5555 ****
--- 5610,5616 ----
         rely on array_subrange to understand how to deal with them). */
        tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
+ #if 0
+       /* array_subrange now calls array_quote_escapes as appropriate, so the
+        caller no longer needs to. */
        if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
        {
***************
*** 5558,5561 ****
--- 5619,5623 ----
        }
        else
+ #endif
        temp = tt;
        break;
***************
*** 5808,5811 ****
--- 5870,5876 ----
      case VT_ARRAYVAR:
        temp = array_patsub (array_cell (v), p, rep, mflags);
+ #if 0
+       /* Don't need to do this anymore; array_patsub calls array_quote_escapes
+        as appropriate before adding the space separators. */
        if (temp && (mflags & MATCH_QUOTED) == 0)
        {
***************
*** 5814,5817 ****
--- 5879,5883 ----
          temp = tt;
        }
+ #endif
        break;
  #endif
*** ../bash-3.2/patchlevel.h    Thu Apr 13 08:31:04 2006
--- patchlevel.h        Mon Oct 16 14:22:54 2006
***************
*** 26,30 ****
     looks for to find the patch level (for the sccs version string). */
  
! #define PATCHLEVEL 13
  
  #endif /* _PATCHLEVEL_H_ */
--- 26,30 ----
     looks for to find the patch level (for the sccs version string). */
  
! #define PATCHLEVEL 14
  
  #endif /* _PATCHLEVEL_H_ */

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
                                Live Strong.
Chet Ramey, ITS, CWRU    chet@case.edu    http://tiswww.tis.case.edu/~chet/




reply via email to

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