BASH PATCH REPORT
|
|
=================
|
|
|
|
Bash-Release: 5.0
|
|
Patch-ID: bash50-003
|
|
|
|
Bug-Reported-by: Andrew Church <achurch+bash@achurch.org>
|
|
Bug-Reference-ID: <5c534aa2.04371@msgid.achurch.org>
|
|
Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2019-01/msg00276.html
|
|
|
|
Bug-Description:
|
|
|
|
There are several incompatibilities in how bash-5.0 processes pathname
|
|
expansion (globbing) of filename arguments that have backslashes in the
|
|
directory portion.
|
|
|
|
Patch (apply with `patch -p0'):
|
|
|
|
*** a/lib/glob/glob_loop.c 2019-01-16 16:13:21.000000000 -0500
|
|
--- b/lib/glob/glob_loop.c 2019-02-01 09:45:11.000000000 -0500
|
|
***************
|
|
*** 27,34 ****
|
|
register const GCHAR *p;
|
|
register GCHAR c;
|
|
! int bopen;
|
|
|
|
p = pattern;
|
|
! bopen = 0;
|
|
|
|
while ((c = *p++) != L('\0'))
|
|
--- 27,34 ----
|
|
register const GCHAR *p;
|
|
register GCHAR c;
|
|
! int bopen, bsquote;
|
|
|
|
p = pattern;
|
|
! bopen = bsquote = 0;
|
|
|
|
while ((c = *p++) != L('\0'))
|
|
***************
|
|
*** 56,66 ****
|
|
case L('\\'):
|
|
/* Don't let the pattern end in a backslash (GMATCH returns no match
|
|
! if the pattern ends in a backslash anyway), but otherwise return 1,
|
|
! since the matching engine uses backslash as an escape character
|
|
! and it can be removed. */
|
|
! return (*p != L('\0'));
|
|
}
|
|
|
|
! return 0;
|
|
}
|
|
|
|
--- 56,75 ----
|
|
case L('\\'):
|
|
/* Don't let the pattern end in a backslash (GMATCH returns no match
|
|
! if the pattern ends in a backslash anyway), but otherwise note that
|
|
! we have seen this, since the matching engine uses backslash as an
|
|
! escape character and it can be removed. We return 2 later if we
|
|
! have seen only backslash-escaped characters, so interested callers
|
|
! know they can shortcut and just dequote the pathname. */
|
|
! if (*p != L('\0'))
|
|
! {
|
|
! p++;
|
|
! bsquote = 1;
|
|
! continue;
|
|
! }
|
|
! else /* (*p == L('\0')) */
|
|
! return 0;
|
|
}
|
|
|
|
! return bsquote ? 2 : 0;
|
|
}
|
|
|
|
*** a/lib/glob/glob.h 2013-10-28 14:46:12.000000000 -0400
|
|
--- b/lib/glob/glob.h 2019-03-07 11:06:47.000000000 -0500
|
|
***************
|
|
*** 31,34 ****
|
|
--- 31,35 ----
|
|
#define GX_ADDCURDIR 0x200 /* internal -- add passed directory name */
|
|
#define GX_GLOBSTAR 0x400 /* turn on special handling of ** */
|
|
+ #define GX_RECURSE 0x800 /* internal -- glob_filename called recursively */
|
|
|
|
extern int glob_pattern_p __P((const char *));
|
|
*** a/lib/glob/glob.c 2018-09-20 10:53:23.000000000 -0400
|
|
--- b/lib/glob/glob.c 2019-03-07 14:23:43.000000000 -0500
|
|
***************
|
|
*** 1062,1066 ****
|
|
unsigned int directory_len;
|
|
int free_dirname; /* flag */
|
|
! int dflags;
|
|
|
|
result = (char **) malloc (sizeof (char *));
|
|
--- 1078,1082 ----
|
|
unsigned int directory_len;
|
|
int free_dirname; /* flag */
|
|
! int dflags, hasglob;
|
|
|
|
result = (char **) malloc (sizeof (char *));
|
|
***************
|
|
*** 1111,1117 ****
|
|
}
|
|
|
|
/* If directory_name contains globbing characters, then we
|
|
! have to expand the previous levels. Just recurse. */
|
|
! if (directory_len > 0 && glob_pattern_p (directory_name))
|
|
{
|
|
char **directories, *d, *p;
|
|
--- 1127,1136 ----
|
|
}
|
|
|
|
+ hasglob = 0;
|
|
/* If directory_name contains globbing characters, then we
|
|
! have to expand the previous levels. Just recurse.
|
|
! If glob_pattern_p returns != [0,1] we have a pattern that has backslash
|
|
! quotes but no unquoted glob pattern characters. We dequote it below. */
|
|
! if (directory_len > 0 && (hasglob = glob_pattern_p (directory_name)) == 1)
|
|
{
|
|
char **directories, *d, *p;
|
|
***************
|
|
*** 1176,1180 ****
|
|
d[directory_len - 1] = '\0';
|
|
|
|
! directories = glob_filename (d, dflags);
|
|
|
|
if (free_dirname)
|
|
--- 1195,1199 ----
|
|
d[directory_len - 1] = '\0';
|
|
|
|
! directories = glob_filename (d, dflags|GX_RECURSE);
|
|
|
|
if (free_dirname)
|
|
***************
|
|
*** 1333,1336 ****
|
|
--- 1352,1369 ----
|
|
return (NULL);
|
|
}
|
|
+ /* If we have a directory name with quoted characters, and we are
|
|
+ being called recursively to glob the directory portion of a pathname,
|
|
+ we need to dequote the directory name before returning it so the
|
|
+ caller can read the directory */
|
|
+ if (directory_len > 0 && hasglob == 2 && (flags & GX_RECURSE) != 0)
|
|
+ {
|
|
+ dequote_pathname (directory_name);
|
|
+ directory_len = strlen (directory_name);
|
|
+ }
|
|
+
|
|
+ /* We could check whether or not the dequoted directory_name is a
|
|
+ directory and return it here, returning the original directory_name
|
|
+ if not, but we don't do that yet. I'm not sure it matters. */
|
|
+
|
|
/* Handle GX_MARKDIRS here. */
|
|
result[0] = (char *) malloc (directory_len + 1);
|
|
*** a/pathexp.c 2018-04-29 17:44:48.000000000 -0400
|
|
--- b/pathexp.c 2019-01-31 20:19:41.000000000 -0500
|
|
***************
|
|
*** 66,74 ****
|
|
register int c;
|
|
char *send;
|
|
! int open;
|
|
|
|
DECLARE_MBSTATE;
|
|
|
|
! open = 0;
|
|
send = string + strlen (string);
|
|
|
|
--- 66,74 ----
|
|
register int c;
|
|
char *send;
|
|
! int open, bsquote;
|
|
|
|
DECLARE_MBSTATE;
|
|
|
|
! open = bsquote = 0;
|
|
send = string + strlen (string);
|
|
|
|
***************
|
|
*** 101,105 ****
|
|
globbing. */
|
|
case '\\':
|
|
! return (*string != 0);
|
|
|
|
case CTLESC:
|
|
--- 101,112 ----
|
|
globbing. */
|
|
case '\\':
|
|
! if (*string != '\0' && *string != '/')
|
|
! {
|
|
! bsquote = 1;
|
|
! string++;
|
|
! continue;
|
|
! }
|
|
! else if (*string == 0)
|
|
! return (0);
|
|
|
|
case CTLESC:
|
|
***************
|
|
*** 118,122 ****
|
|
#endif
|
|
}
|
|
! return (0);
|
|
}
|
|
|
|
--- 125,130 ----
|
|
#endif
|
|
}
|
|
!
|
|
! return (bsquote ? 2 : 0);
|
|
}
|
|
|
|
*** a/bashline.c 2019-01-16 16:13:21.000000000 -0500
|
|
--- b/bashline.c 2019-02-22 09:29:08.000000000 -0500
|
|
***************
|
|
*** 3753,3757 ****
|
|
|
|
case '\\':
|
|
! if (*string == 0)
|
|
return (0);
|
|
}
|
|
--- 3766,3770 ----
|
|
|
|
case '\\':
|
|
! if (*string++ == 0)
|
|
return (0);
|
|
}
|
|
*** a/patchlevel.h 2016-06-22 14:51:03.000000000 -0400
|
|
--- b/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 2
|
|
|
|
#endif /* _PATCHLEVEL_H_ */
|
|
--- 26,30 ----
|
|
looks for to find the patch level (for the sccs version string). */
|
|
|
|
! #define PATCHLEVEL 3
|
|
|
|
#endif /* _PATCHLEVEL_H_ */
|