]>
Commit | Line | Data |
---|---|---|
415fb8b5 PM |
1 | BASH PATCH REPORT |
2 | ================= | |
3 | ||
4 | Bash-Release: 5.0 | |
5 | Patch-ID: bash50-003 | |
6 | ||
7 | Bug-Reported-by: Andrew Church <achurch+bash@achurch.org> | |
8 | Bug-Reference-ID: <5c534aa2.04371@msgid.achurch.org> | |
9 | Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2019-01/msg00276.html | |
10 | ||
11 | Bug-Description: | |
12 | ||
13 | There are several incompatibilities in how bash-5.0 processes pathname | |
14 | expansion (globbing) of filename arguments that have backslashes in the | |
15 | directory portion. | |
16 | ||
17 | Patch (apply with `patch -p0'): | |
18 | ||
19 | *** ../bash-5.0-patched/lib/glob/glob_loop.c 2019-01-16 16:13:21.000000000 -0500 | |
20 | --- lib/glob/glob_loop.c 2019-02-01 09:45:11.000000000 -0500 | |
21 | *************** | |
22 | *** 27,34 **** | |
23 | register const GCHAR *p; | |
24 | register GCHAR c; | |
25 | ! int bopen; | |
26 | ||
27 | p = pattern; | |
28 | ! bopen = 0; | |
29 | ||
30 | while ((c = *p++) != L('\0')) | |
31 | --- 27,34 ---- | |
32 | register const GCHAR *p; | |
33 | register GCHAR c; | |
34 | ! int bopen, bsquote; | |
35 | ||
36 | p = pattern; | |
37 | ! bopen = bsquote = 0; | |
38 | ||
39 | while ((c = *p++) != L('\0')) | |
40 | *************** | |
41 | *** 56,66 **** | |
42 | case L('\\'): | |
43 | /* Don't let the pattern end in a backslash (GMATCH returns no match | |
44 | ! if the pattern ends in a backslash anyway), but otherwise return 1, | |
45 | ! since the matching engine uses backslash as an escape character | |
46 | ! and it can be removed. */ | |
47 | ! return (*p != L('\0')); | |
48 | } | |
49 | ||
50 | ! return 0; | |
51 | } | |
52 | ||
53 | --- 56,75 ---- | |
54 | case L('\\'): | |
55 | /* Don't let the pattern end in a backslash (GMATCH returns no match | |
56 | ! if the pattern ends in a backslash anyway), but otherwise note that | |
57 | ! we have seen this, since the matching engine uses backslash as an | |
58 | ! escape character and it can be removed. We return 2 later if we | |
59 | ! have seen only backslash-escaped characters, so interested callers | |
60 | ! know they can shortcut and just dequote the pathname. */ | |
61 | ! if (*p != L('\0')) | |
62 | ! { | |
63 | ! p++; | |
64 | ! bsquote = 1; | |
65 | ! continue; | |
66 | ! } | |
67 | ! else /* (*p == L('\0')) */ | |
68 | ! return 0; | |
69 | } | |
70 | ||
71 | ! return bsquote ? 2 : 0; | |
72 | } | |
73 | ||
74 | *** ../bash-5.0-patched/lib/glob/glob.h 2013-10-28 14:46:12.000000000 -0400 | |
75 | --- lib/glob/glob.h 2019-03-07 11:06:47.000000000 -0500 | |
76 | *************** | |
77 | *** 31,34 **** | |
78 | --- 31,35 ---- | |
79 | #define GX_ADDCURDIR 0x200 /* internal -- add passed directory name */ | |
80 | #define GX_GLOBSTAR 0x400 /* turn on special handling of ** */ | |
81 | + #define GX_RECURSE 0x800 /* internal -- glob_filename called recursively */ | |
82 | ||
83 | extern int glob_pattern_p __P((const char *)); | |
84 | *** ../bash-5.0-patched/lib/glob/glob.c 2018-09-20 10:53:23.000000000 -0400 | |
85 | --- lib/glob/glob.c 2019-03-07 14:23:43.000000000 -0500 | |
86 | *************** | |
87 | *** 1062,1066 **** | |
88 | unsigned int directory_len; | |
89 | int free_dirname; /* flag */ | |
90 | ! int dflags; | |
91 | ||
92 | result = (char **) malloc (sizeof (char *)); | |
93 | --- 1078,1082 ---- | |
94 | unsigned int directory_len; | |
95 | int free_dirname; /* flag */ | |
96 | ! int dflags, hasglob; | |
97 | ||
98 | result = (char **) malloc (sizeof (char *)); | |
99 | *************** | |
100 | *** 1111,1117 **** | |
101 | } | |
102 | ||
103 | /* If directory_name contains globbing characters, then we | |
104 | ! have to expand the previous levels. Just recurse. */ | |
105 | ! if (directory_len > 0 && glob_pattern_p (directory_name)) | |
106 | { | |
107 | char **directories, *d, *p; | |
108 | --- 1127,1136 ---- | |
109 | } | |
110 | ||
111 | + hasglob = 0; | |
112 | /* If directory_name contains globbing characters, then we | |
113 | ! have to expand the previous levels. Just recurse. | |
114 | ! If glob_pattern_p returns != [0,1] we have a pattern that has backslash | |
115 | ! quotes but no unquoted glob pattern characters. We dequote it below. */ | |
116 | ! if (directory_len > 0 && (hasglob = glob_pattern_p (directory_name)) == 1) | |
117 | { | |
118 | char **directories, *d, *p; | |
119 | *************** | |
120 | *** 1176,1180 **** | |
121 | d[directory_len - 1] = '\0'; | |
122 | ||
123 | ! directories = glob_filename (d, dflags); | |
124 | ||
125 | if (free_dirname) | |
126 | --- 1195,1199 ---- | |
127 | d[directory_len - 1] = '\0'; | |
128 | ||
129 | ! directories = glob_filename (d, dflags|GX_RECURSE); | |
130 | ||
131 | if (free_dirname) | |
132 | *************** | |
133 | *** 1333,1336 **** | |
134 | --- 1352,1369 ---- | |
135 | return (NULL); | |
136 | } | |
137 | + /* If we have a directory name with quoted characters, and we are | |
138 | + being called recursively to glob the directory portion of a pathname, | |
139 | + we need to dequote the directory name before returning it so the | |
140 | + caller can read the directory */ | |
141 | + if (directory_len > 0 && hasglob == 2 && (flags & GX_RECURSE) != 0) | |
142 | + { | |
143 | + dequote_pathname (directory_name); | |
144 | + directory_len = strlen (directory_name); | |
145 | + } | |
146 | + | |
147 | + /* We could check whether or not the dequoted directory_name is a | |
148 | + directory and return it here, returning the original directory_name | |
149 | + if not, but we don't do that yet. I'm not sure it matters. */ | |
150 | + | |
151 | /* Handle GX_MARKDIRS here. */ | |
152 | result[0] = (char *) malloc (directory_len + 1); | |
153 | *** ../bash-5.0-patched/pathexp.c 2018-04-29 17:44:48.000000000 -0400 | |
154 | --- pathexp.c 2019-01-31 20:19:41.000000000 -0500 | |
155 | *************** | |
156 | *** 66,74 **** | |
157 | register int c; | |
158 | char *send; | |
159 | ! int open; | |
160 | ||
161 | DECLARE_MBSTATE; | |
162 | ||
163 | ! open = 0; | |
164 | send = string + strlen (string); | |
165 | ||
166 | --- 66,74 ---- | |
167 | register int c; | |
168 | char *send; | |
169 | ! int open, bsquote; | |
170 | ||
171 | DECLARE_MBSTATE; | |
172 | ||
173 | ! open = bsquote = 0; | |
174 | send = string + strlen (string); | |
175 | ||
176 | *************** | |
177 | *** 101,105 **** | |
178 | globbing. */ | |
179 | case '\\': | |
180 | ! return (*string != 0); | |
181 | ||
182 | case CTLESC: | |
183 | --- 101,112 ---- | |
184 | globbing. */ | |
185 | case '\\': | |
186 | ! if (*string != '\0' && *string != '/') | |
187 | ! { | |
188 | ! bsquote = 1; | |
189 | ! string++; | |
190 | ! continue; | |
191 | ! } | |
192 | ! else if (*string == 0) | |
193 | ! return (0); | |
194 | ||
195 | case CTLESC: | |
196 | *************** | |
197 | *** 118,122 **** | |
198 | #endif | |
199 | } | |
200 | ! return (0); | |
201 | } | |
202 | ||
203 | --- 125,130 ---- | |
204 | #endif | |
205 | } | |
206 | ! | |
207 | ! return (bsquote ? 2 : 0); | |
208 | } | |
209 | ||
210 | *** ../bash-5.0-patched/bashline.c 2019-01-16 16:13:21.000000000 -0500 | |
211 | --- bashline.c 2019-02-22 09:29:08.000000000 -0500 | |
212 | *************** | |
213 | *** 3753,3757 **** | |
214 | ||
215 | case '\\': | |
216 | ! if (*string == 0) | |
217 | return (0); | |
218 | } | |
219 | --- 3766,3770 ---- | |
220 | ||
221 | case '\\': | |
222 | ! if (*string++ == 0) | |
223 | return (0); | |
224 | } | |
225 | *** ../bash-5.0/patchlevel.h 2016-06-22 14:51:03.000000000 -0400 | |
226 | --- patchlevel.h 2016-10-01 11:01:28.000000000 -0400 | |
227 | *************** | |
228 | *** 26,30 **** | |
229 | looks for to find the patch level (for the sccs version string). */ | |
230 | ||
231 | ! #define PATCHLEVEL 2 | |
232 | ||
233 | #endif /* _PATCHLEVEL_H_ */ | |
234 | --- 26,30 ---- | |
235 | looks for to find the patch level (for the sccs version string). */ | |
236 | ||
237 | ! #define PATCHLEVEL 3 | |
238 | ||
239 | #endif /* _PATCHLEVEL_H_ */ |