308 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			308 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 			     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_ */
 |