posix: Sync glob code with gnulib

It sync with gnulib commit 43ee1a6bf and fixes and use-after-free
bug (gnulib commit 717766da8926e36).

Checked on x86_64-linux-gnu.
This commit is contained in:
Adhemerval Zanella 2020-12-29 17:41:19 -03:00
parent c2a150d089
commit 4883360415
3 changed files with 836 additions and 816 deletions

View File

@ -15,6 +15,16 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _LIBC
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the pattern == NULL test below. */
# define _GL_ARG_NONNULL(params)
# include <config.h>
#endif
#include <glob.h>
#include <errno.h>
@ -26,7 +36,7 @@
#include <assert.h>
#include <unistd.h>
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
#if defined _WIN32 && ! defined __CYGWIN__
# define WINDOWS32
#endif
@ -56,7 +66,12 @@
# define __glob glob
# define __getlogin_r(buf, len) getlogin_r (buf, len)
# define __lstat64(fname, buf) lstat (fname, buf)
# if defined _WIN32 && !defined __CYGWIN__
/* Avoid GCC or clang warning. The original __stat64 macro is unused. */
# undef __stat64
# endif
# define __stat64(fname, buf) stat (fname, buf)
# define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag)
# define struct_stat64 struct stat
# ifndef __MVS__
# define __alloca alloca
@ -73,7 +88,9 @@
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
typedef uint_fast8_t dirent_type;
/* The type of ((struct dirent *) 0)->d_type is 'unsigned char' on most
platforms, but 'unsigned int' in the mingw from mingw.org. */
typedef uint_fast32_t dirent_type;
#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
/* Any distinct values will do here.
@ -204,7 +221,7 @@ glob_lstat (glob_t *pglob, int flags, const char *fullname)
static bool
size_add_wrapv (size_t a, size_t b, size_t *r)
{
#if 5 <= __GNUC__ && !defined __ICC
#if 7 <= __GNUC__ && !defined __ICC
return __builtin_add_overflow (a, b, r);
#else
*r = a + b;
@ -820,31 +837,34 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
{
size_t home_len = strlen (p->pw_dir);
size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
char *d, *newp;
bool use_alloca = glob_use_alloca (alloca_used,
home_len + rest_len + 1);
/* dirname contains end_name; we can't free it now. */
char *prev_dirname =
(__glibc_unlikely (malloc_dirname) ? dirname : NULL);
char *d;
if (use_alloca)
newp = alloca_account (home_len + rest_len + 1, alloca_used);
malloc_dirname = 0;
if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
dirname = alloca_account (home_len + rest_len + 1,
alloca_used);
else
{
newp = malloc (home_len + rest_len + 1);
if (newp == NULL)
dirname = malloc (home_len + rest_len + 1);
if (dirname == NULL)
{
free (prev_dirname);
scratch_buffer_free (&pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
malloc_dirname = 1;
}
d = mempcpy (newp, p->pw_dir, home_len);
d = mempcpy (dirname, p->pw_dir, home_len);
if (end_name != NULL)
d = mempcpy (d, end_name, rest_len);
*d = '\0';
if (__glibc_unlikely (malloc_dirname))
free (dirname);
dirname = newp;
malloc_dirname = !use_alloca;
free (prev_dirname);
dirlen = home_len + rest_len;
dirname_modified = 1;

View File

@ -17,7 +17,7 @@
<https://www.gnu.org/licenses/>. */
#ifndef _LIBC
# include <config.h>
# include <libc-config.h>
#endif
#include <glob.h>

View File

@ -17,7 +17,7 @@
<https://www.gnu.org/licenses/>. */
#ifndef _LIBC
# include <config.h>
# include <libc-config.h>
#endif
#include <glob.h>