You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
6.2 KiB

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