summaryrefslogtreecommitdiff
path: root/data/bash/bash44-012
blob: 182fd7cb137d60876a8c1d37c1d87ccb14cbe3ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
			     BASH PATCH REPORT
			     =================

Bash-Release:	4.4
Patch-ID:	bash44-012

Bug-Reported-by:	Clark Wang <dearvoid@gmail.com>
Bug-Reference-ID:	<CADv8-ojttPUFOZXqbjsvy83LfaJtQKZ5qejGdF6j0VJ3vtrYOA@mail.gmail.com>
Bug-Reference-URL:	http://lists.gnu.org/archive/html/bug-bash/2016-11/msg00106.html

Bug-Description:

When -N is used, the input is not supposed to be split using $IFS, but
leading and trailing IFS whitespace was still removed.

Patch (apply with `patch -p0'):

*** ../bash-4.4-patched/subst.c	2017-01-20 14:22:01.000000000 -0500
--- subst.c	2017-01-25 13:43:22.000000000 -0500
***************
*** 2826,2834 ****
  /* Parse a single word from STRING, using SEPARATORS to separate fields.
     ENDPTR is set to the first character after the word.  This is used by
!    the `read' builtin.  This is never called with SEPARATORS != $IFS;
!    it should be simplified.
  
     XXX - this function is very similar to list_string; they should be
  	 combined - XXX */
  char *
  get_word_from_string (stringp, separators, endptr)
--- 2826,2838 ----
  /* Parse a single word from STRING, using SEPARATORS to separate fields.
     ENDPTR is set to the first character after the word.  This is used by
!    the `read' builtin.
!    
!    This is never called with SEPARATORS != $IFS, and takes advantage of that.
  
     XXX - this function is very similar to list_string; they should be
  	 combined - XXX */
+ 
+ #define islocalsep(c)	(local_cmap[(unsigned char)(c)] != 0)
+ 
  char *
  get_word_from_string (stringp, separators, endptr)
***************
*** 2838,2841 ****
--- 2842,2846 ----
    char *current_word;
    int sindex, sh_style_split, whitesep, xflags;
+   unsigned char local_cmap[UCHAR_MAX+1];	/* really only need single-byte chars here */
    size_t slen;
  
***************
*** 2847,2854 ****
  				 separators[2] == '\n' &&
  				 separators[3] == '\0';
!   for (xflags = 0, s = ifs_value; s && *s; s++)
      {
        if (*s == CTLESC) xflags |= SX_NOCTLESC;
        if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
      }
  
--- 2852,2861 ----
  				 separators[2] == '\n' &&
  				 separators[3] == '\0';
!   memset (local_cmap, '\0', sizeof (local_cmap));
!   for (xflags = 0, s = separators; s && *s; s++)
      {
        if (*s == CTLESC) xflags |= SX_NOCTLESC;
        if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
+       local_cmap[(unsigned char)*s] = 1;	/* local charmap of separators */
      }
  
***************
*** 2857,2864 ****
  
    /* Remove sequences of whitespace at the beginning of STRING, as
!      long as those characters appear in IFS. */
!   if (sh_style_split || !separators || !*separators)
      {
!       for (; *s && spctabnl (*s) && isifs (*s); s++);
  
        /* If the string is nothing but whitespace, update it and return. */
--- 2864,2872 ----
  
    /* Remove sequences of whitespace at the beginning of STRING, as
!      long as those characters appear in SEPARATORS.  This happens if
!      SEPARATORS == $' \t\n' or if IFS is unset. */
!   if (sh_style_split || separators == 0)
      {
!       for (; *s && spctabnl (*s) && islocalsep (*s); s++);
  
        /* If the string is nothing but whitespace, update it and return. */
***************
*** 2879,2885 ****
       This obeys the field splitting rules in Posix.2. */
    sindex = 0;
!   /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
!      unless multibyte chars are possible. */
!   slen = (MB_CUR_MAX > 1) ? STRLEN (s) : 1;
    current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
  
--- 2887,2893 ----
       This obeys the field splitting rules in Posix.2. */
    sindex = 0;
!   /* Don't need string length in ADVANCE_CHAR unless multibyte chars are
!      possible, but need it in string_extract_verbatim for bounds checking */
!   slen = STRLEN (s);
    current_word = string_extract_verbatim (s, slen, &sindex, separators, xflags);
  
***************
*** 2900,2904 ****
    /* Now skip sequences of space, tab, or newline characters if they are
       in the list of separators. */
!   while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
      sindex++;
  
--- 2908,2912 ----
    /* Now skip sequences of space, tab, or newline characters if they are
       in the list of separators. */
!   while (s[sindex] && spctabnl (s[sindex]) && islocalsep (s[sindex]))
      sindex++;
  
***************
*** 2907,2916 ****
       delimiter, not a separate delimiter that would result in an empty field.
       Look at POSIX.2, 3.6.5, (3)(b). */
!   if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
      {
        sindex++;
        /* An IFS character that is not IFS white space, along with any adjacent
  	 IFS white space, shall delimit a field. */
!       while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
  	sindex++;
      }
--- 2915,2924 ----
       delimiter, not a separate delimiter that would result in an empty field.
       Look at POSIX.2, 3.6.5, (3)(b). */
!   if (s[sindex] && whitesep && islocalsep (s[sindex]) && !spctabnl (s[sindex]))
      {
        sindex++;
        /* An IFS character that is not IFS white space, along with any adjacent
  	 IFS white space, shall delimit a field. */
!       while (s[sindex] && spctabnl (s[sindex]) && islocalsep(s[sindex]))
  	sindex++;
      }
*** ../bash-4.4/patchlevel.h	2016-06-22 14:51:03.000000000 -0400
--- patchlevel.h	2016-10-01 11:01:28.000000000 -0400
***************
*** 26,30 ****
     looks for to find the patch level (for the sccs version string). */
  
! #define PATCHLEVEL 11
  
  #endif /* _PATCHLEVEL_H_ */
--- 26,30 ----
     looks for to find the patch level (for the sccs version string). */
  
! #define PATCHLEVEL 12
  
  #endif /* _PATCHLEVEL_H_ */