blob: 12edb16a2a4878928cf473e97c1502f889a14b3a [file] [log] [blame]
From https://ftp.gnu.org/gnu/bash/bash-5.0-patches/bash50-003
Signed-off-by: Pascal de Bruijn <p.debruijn@unilogic.nl>
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'):
*** ../bash-5.0-patched/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;
}
*** ../bash-5.0-patched/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 *));
*** ../bash-5.0-patched/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);
*** ../bash-5.0-patched/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);
}
*** ../bash-5.0-patched/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);
}
*** ../bash-5.0/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_ */