forked from pool/glibc
2245 lines
68 KiB
Diff
2245 lines
68 KiB
Diff
|
2017-10-22 Paul Eggert <eggert@cs.ucla.edu>
|
|||
|
|
|||
|
[BZ #22332]
|
|||
|
* posix/glob.c (__glob): Fix buffer overflow during GLOB_TILDE
|
|||
|
unescaping.
|
|||
|
|
|||
|
2017-10-21 Florian Weimer <fweimer@redhat.com>
|
|||
|
|
|||
|
* posix/Makefile (tests): Add tst-glob-tilde.
|
|||
|
(tests-special): Add tst-glob-tilde-mem.out
|
|||
|
(tst-glob-tilde-ENV): Set MALLOC_TRACE.
|
|||
|
(tst-glob-tilde-mem.out): Add mtrace check.
|
|||
|
* posix/tst-glob-tilde.c: New file.
|
|||
|
|
|||
|
2017-10-20 Paul Eggert <eggert@cs.ucla.edu>
|
|||
|
|
|||
|
[BZ #22320]
|
|||
|
CVE-2017-15670
|
|||
|
* posix/glob.c (__glob): Fix one-byte overflow.
|
|||
|
|
|||
|
2017-09-08 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|||
|
|
|||
|
[BZ #1062]
|
|||
|
[BZ #22325]
|
|||
|
CVE-2017-15671
|
|||
|
* posix/Makefile (routines): Add globfree, globfree64, and
|
|||
|
glob_pattern_p.
|
|||
|
* posix/flexmember.h: New file.
|
|||
|
* posix/glob_internal.h: Likewise.
|
|||
|
* posix/glob_pattern_p.c: Likewise.
|
|||
|
* posix/globfree.c: Likewise.
|
|||
|
* posix/globfree64.c: Likewise.
|
|||
|
* sysdeps/gnu/globfree64.c: Likewise.
|
|||
|
* sysdeps/unix/sysv/linux/alpha/globfree.c: Likewise.
|
|||
|
* sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c: Likewise.
|
|||
|
* sysdeps/unix/sysv/linux/oldglob.c: Likewise.
|
|||
|
* sysdeps/unix/sysv/linux/wordsize-64/globfree64.c: Likewise.
|
|||
|
* sysdeps/unix/sysv/linux/x86_64/x32/globfree.c: Likewise.
|
|||
|
* sysdeps/wordsize-64/globfree.c: Likewise.
|
|||
|
* sysdeps/wordsize-64/globfree64.c: Likewise.
|
|||
|
* posix/glob.c (HAVE_CONFIG_H): Use !_LIBC instead.
|
|||
|
[NDEBUG): Remove comments.
|
|||
|
(GLOB_ONLY_P, _AMIGA, VMS): Remove define.
|
|||
|
(dirent_type): New type. Use uint_fast8_t not
|
|||
|
uint8_t, as C99 does not require uint8_t.
|
|||
|
(DT_UNKNOWN, DT_DIR, DT_LNK): New macros.
|
|||
|
(struct readdir_result): Use dirent_type. Do not define skip_entry
|
|||
|
unless it is needed; this saves a byte on platforms lacking d_ino.
|
|||
|
(readdir_result_type, readdir_result_skip_entry):
|
|||
|
New functions, replacing ...
|
|||
|
(readdir_result_might_be_symlink, readdir_result_might_be_dir):
|
|||
|
these functions, which were removed. This makes the callers
|
|||
|
easier to read. All callers changed.
|
|||
|
(D_INO_TO_RESULT): Now empty if there is no d_ino.
|
|||
|
(size_add_wrapv, glob_use_alloca): New static functions.
|
|||
|
(glob, glob_in_dir): Check for size_t overflow in several places,
|
|||
|
and fix some size_t checks that were not quite right.
|
|||
|
Remove old code using SHELL since Bash no longer
|
|||
|
uses this.
|
|||
|
(glob, prefix_array): Separate MS code better.
|
|||
|
(glob_in_dir): Remove old Amiga and VMS code.
|
|||
|
(globfree, __glob_pattern_type, __glob_pattern_p): Move to
|
|||
|
separate files.
|
|||
|
(glob_in_dir): Do not rely on undefined behavior in accessing
|
|||
|
struct members beyond their bounds. Use a flexible array member
|
|||
|
instead
|
|||
|
(link_stat): Rename from link_exists2_p and return -1/0 instead of
|
|||
|
0/1. Caller changed.
|
|||
|
(glob): Fix memory leaks.
|
|||
|
* posix/glob64 (globfree64): Move to separate file.
|
|||
|
* sysdeps/gnu/glob64.c (NO_GLOB_PATTERN_P): Remove define.
|
|||
|
(globfree64): Remove hidden alias.
|
|||
|
* sysdeps/unix/sysv/linux/Makefile (sysdeps_routines): Add
|
|||
|
oldglob.
|
|||
|
* sysdeps/unix/sysv/linux/alpha/glob.c (__new_globfree): Move to
|
|||
|
separate file.
|
|||
|
* sysdeps/unix/sysv/linux/i386/glob64.c (NO_GLOB_PATTERN_P): Remove
|
|||
|
define.
|
|||
|
Move compat code to separate file.
|
|||
|
* sysdeps/wordsize-64/glob.c (globfree): Move definitions to
|
|||
|
separate file.
|
|||
|
|
|||
|
2017-08-20 H.J. Lu <hongjiu.lu@intel.com>
|
|||
|
|
|||
|
[BZ #18822]
|
|||
|
* sysdeps/unix/sysv/linux/i386/glob64.c (__old_glob64): Add
|
|||
|
libc_hidden_proto and libc_hidden_def.
|
|||
|
|
|||
|
Index: glibc-2.26/posix/Makefile
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/posix/Makefile
|
|||
|
+++ glibc-2.26/posix/Makefile
|
|||
|
@@ -45,7 +45,7 @@ routines := \
|
|||
|
getpgid setpgid getpgrp bsd-getpgrp setpgrp getsid setsid \
|
|||
|
getresuid getresgid setresuid setresgid \
|
|||
|
pathconf sysconf fpathconf \
|
|||
|
- glob glob64 fnmatch regex \
|
|||
|
+ glob glob64 globfree globfree64 glob_pattern_p fnmatch regex \
|
|||
|
confstr \
|
|||
|
getopt getopt1 \
|
|||
|
sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax \
|
|||
|
@@ -93,7 +93,7 @@ tests := test-errno tstgetopt testfnm r
|
|||
|
tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \
|
|||
|
tst-posix_spawn-fd tst-posix_spawn-setsid \
|
|||
|
tst-posix_fadvise tst-posix_fadvise64 \
|
|||
|
- tst-sysconf-empty-chroot
|
|||
|
+ tst-sysconf-empty-chroot tst-glob-tilde
|
|||
|
tests-internal := bug-regex5 bug-regex20 bug-regex33 \
|
|||
|
tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3
|
|||
|
xtests := bug-ga2
|
|||
|
@@ -141,7 +141,8 @@ tests-special += $(objpfx)bug-regex2-mem
|
|||
|
$(objpfx)tst-rxspencer-no-utf8-mem.out $(objpfx)tst-pcre-mem.out \
|
|||
|
$(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
|
|||
|
$(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
|
|||
|
- $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out
|
|||
|
+ $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out \
|
|||
|
+ $(objpfx)tst-glob-tilde-mem.out
|
|||
|
xtests-special += $(objpfx)bug-ga2-mem.out
|
|||
|
endif
|
|||
|
|
|||
|
@@ -350,6 +351,12 @@ $(objpfx)bug-glob2-mem.out: $(objpfx)bug
|
|||
|
$(common-objpfx)malloc/mtrace $(objpfx)bug-glob2.mtrace > $@; \
|
|||
|
$(evaluate-test)
|
|||
|
|
|||
|
+tst-glob-tilde-ENV = MALLOC_TRACE=$(objpfx)tst-glob-tilde.mtrace
|
|||
|
+
|
|||
|
+$(objpfx)tst-glob-tilde-mem.out: $(objpfx)tst-glob-tilde.out
|
|||
|
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-glob-tilde.mtrace > $@; \
|
|||
|
+ $(evaluate-test)
|
|||
|
+
|
|||
|
$(inst_libexecdir)/getconf: $(inst_bindir)/getconf \
|
|||
|
$(objpfx)getconf.speclist FORCE
|
|||
|
$(addprefix $(..)./scripts/mkinstalldirs ,\
|
|||
|
Index: glibc-2.26/posix/flexmember.h
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/posix/flexmember.h
|
|||
|
@@ -0,0 +1,45 @@
|
|||
|
+/* Sizes of structs with flexible array members.
|
|||
|
+
|
|||
|
+ Copyright 2016-2017 Free Software Foundation, Inc.
|
|||
|
+
|
|||
|
+ This file is part of the GNU C Library.
|
|||
|
+
|
|||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|||
|
+ modify it under the terms of the GNU Lesser General Public
|
|||
|
+ License as published by the Free Software Foundation; either
|
|||
|
+ version 2.1 of the License, or (at your option) any later version.
|
|||
|
+
|
|||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ Lesser General Public License for more details.
|
|||
|
+
|
|||
|
+ You should have received a copy of the GNU Lesser General Public
|
|||
|
+ License along with the GNU C Library; if not, see
|
|||
|
+ <http://www.gnu.org/licenses/>.
|
|||
|
+
|
|||
|
+ Written by Paul Eggert. */
|
|||
|
+
|
|||
|
+#include <stddef.h>
|
|||
|
+
|
|||
|
+/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
|
|||
|
+ On older platforms without _Alignof, use a pessimistic bound that is
|
|||
|
+ safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
|
|||
|
+ On newer platforms, use _Alignof to get a tighter bound. */
|
|||
|
+
|
|||
|
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
|
|||
|
+# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
|
|||
|
+#else
|
|||
|
+# define FLEXALIGNOF(type) _Alignof (type)
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+/* Upper bound on the size of a struct of type TYPE with a flexible
|
|||
|
+ array member named MEMBER that is followed by N bytes of other data.
|
|||
|
+ This is not simply sizeof (TYPE) + N, since it may require
|
|||
|
+ alignment on unusually picky C11 platforms, and
|
|||
|
+ FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms.
|
|||
|
+ Yield a value less than N if and only if arithmetic overflow occurs. */
|
|||
|
+
|
|||
|
+#define FLEXSIZEOF(type, member, n) \
|
|||
|
+ ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
|
|||
|
+ & ~ (FLEXALIGNOF (type) - 1))
|
|||
|
Index: glibc-2.26/posix/glob.c
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/posix/glob.c
|
|||
|
+++ glibc-2.26/posix/glob.c
|
|||
|
@@ -15,7 +15,7 @@
|
|||
|
License along with the GNU C Library; if not, see
|
|||
|
<http://www.gnu.org/licenses/>. */
|
|||
|
|
|||
|
-#ifdef HAVE_CONFIG_H
|
|||
|
+#ifndef _LIBC
|
|||
|
# include <config.h>
|
|||
|
#endif
|
|||
|
|
|||
|
@@ -27,29 +27,15 @@
|
|||
|
#include <stdbool.h>
|
|||
|
#include <stddef.h>
|
|||
|
#include <stdint.h>
|
|||
|
-
|
|||
|
-/* Outcomment the following line for production quality code. */
|
|||
|
-/* #define NDEBUG 1 */
|
|||
|
#include <assert.h>
|
|||
|
+#include <unistd.h>
|
|||
|
|
|||
|
-#include <stdio.h> /* Needed on stupid SunOS for assert. */
|
|||
|
-
|
|||
|
-#if !defined _LIBC || !defined GLOB_ONLY_P
|
|||
|
-#if defined HAVE_UNISTD_H || defined _LIBC
|
|||
|
-# include <unistd.h>
|
|||
|
-# ifndef POSIX
|
|||
|
-# ifdef _POSIX_VERSION
|
|||
|
-# define POSIX
|
|||
|
-# endif
|
|||
|
-# endif
|
|||
|
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
|
|||
|
+# define WINDOWS32
|
|||
|
#endif
|
|||
|
|
|||
|
-#include <pwd.h>
|
|||
|
-
|
|||
|
-#if defined HAVE_STDINT_H || defined _LIBC
|
|||
|
-# include <stdint.h>
|
|||
|
-#elif !defined UINTPTR_MAX
|
|||
|
-# define UINTPTR_MAX (~((size_t) 0))
|
|||
|
+#ifndef WINDOWS32
|
|||
|
+# include <pwd.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#include <errno.h>
|
|||
|
@@ -57,24 +43,7 @@
|
|||
|
# define __set_errno(val) errno = (val)
|
|||
|
#endif
|
|||
|
|
|||
|
-#if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__
|
|||
|
-# include <dirent.h>
|
|||
|
-#else
|
|||
|
-# define dirent direct
|
|||
|
-# ifdef HAVE_SYS_NDIR_H
|
|||
|
-# include <sys/ndir.h>
|
|||
|
-# endif
|
|||
|
-# ifdef HAVE_SYS_DIR_H
|
|||
|
-# include <sys/dir.h>
|
|||
|
-# endif
|
|||
|
-# ifdef HAVE_NDIR_H
|
|||
|
-# include <ndir.h>
|
|||
|
-# endif
|
|||
|
-# ifdef HAVE_VMSDIR_H
|
|||
|
-# include "vmsdir.h"
|
|||
|
-# endif /* HAVE_VMSDIR_H */
|
|||
|
-#endif
|
|||
|
-
|
|||
|
+#include <dirent.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <alloca.h>
|
|||
|
@@ -87,27 +56,29 @@
|
|||
|
# define opendir(name) __opendir (name)
|
|||
|
# define readdir(str) __readdir64 (str)
|
|||
|
# define getpwnam_r(name, bufp, buf, len, res) \
|
|||
|
- __getpwnam_r (name, bufp, buf, len, res)
|
|||
|
+ __getpwnam_r (name, bufp, buf, len, res)
|
|||
|
# ifndef __stat64
|
|||
|
# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
|
|||
|
# endif
|
|||
|
# define struct_stat64 struct stat64
|
|||
|
+# define FLEXIBLE_ARRAY_MEMBER
|
|||
|
#else /* !_LIBC */
|
|||
|
-# include "getlogin_r.h"
|
|||
|
-# include "mempcpy.h"
|
|||
|
-# include "stat-macros.h"
|
|||
|
-# include "strdup.h"
|
|||
|
-# define __stat64(fname, buf) stat (fname, buf)
|
|||
|
-# define struct_stat64 struct stat
|
|||
|
-# define __stat(fname, buf) stat (fname, buf)
|
|||
|
-# define __alloca alloca
|
|||
|
-# define __readdir readdir
|
|||
|
-# define __readdir64 readdir64
|
|||
|
-# define __glob_pattern_p glob_pattern_p
|
|||
|
+# define __getlogin_r(buf, len) getlogin_r (buf, len)
|
|||
|
+# 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
|
|||
|
+# endif
|
|||
|
+# define __readdir readdir
|
|||
|
+# define COMPILE_GLOB64
|
|||
|
#endif /* _LIBC */
|
|||
|
|
|||
|
#include <fnmatch.h>
|
|||
|
|
|||
|
+#include <flexmember.h>
|
|||
|
+#include <glob_internal.h>
|
|||
|
+
|
|||
|
#ifdef _SC_GETPW_R_SIZE_MAX
|
|||
|
# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX)
|
|||
|
#else
|
|||
|
@@ -121,61 +92,59 @@
|
|||
|
|
|||
|
static const char *next_brace_sub (const char *begin, int flags) __THROWNL;
|
|||
|
|
|||
|
+typedef uint_fast8_t dirent_type;
|
|||
|
+
|
|||
|
+#if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE
|
|||
|
+/* Any distinct values will do here.
|
|||
|
+ Undef any existing macros out of the way. */
|
|||
|
+# undef DT_UNKNOWN
|
|||
|
+# undef DT_DIR
|
|||
|
+# undef DT_LNK
|
|||
|
+# define DT_UNKNOWN 0
|
|||
|
+# define DT_DIR 1
|
|||
|
+# define DT_LNK 2
|
|||
|
+#endif
|
|||
|
+
|
|||
|
/* A representation of a directory entry which does not depend on the
|
|||
|
layout of struct dirent, or the size of ino_t. */
|
|||
|
struct readdir_result
|
|||
|
{
|
|||
|
const char *name;
|
|||
|
-# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
|||
|
- uint8_t type;
|
|||
|
-# endif
|
|||
|
+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
|||
|
+ dirent_type type;
|
|||
|
+#endif
|
|||
|
+#if defined _LIBC || defined D_INO_IN_DIRENT
|
|||
|
bool skip_entry;
|
|||
|
+#endif
|
|||
|
};
|
|||
|
|
|||
|
-# if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
|||
|
-/* Initializer based on the d_type member of struct dirent. */
|
|||
|
-# define D_TYPE_TO_RESULT(source) (source)->d_type,
|
|||
|
-
|
|||
|
-/* True if the directory entry D might be a symbolic link. */
|
|||
|
-static bool
|
|||
|
-readdir_result_might_be_symlink (struct readdir_result d)
|
|||
|
-{
|
|||
|
- return d.type == DT_UNKNOWN || d.type == DT_LNK;
|
|||
|
-}
|
|||
|
-
|
|||
|
-/* True if the directory entry D might be a directory. */
|
|||
|
-static bool
|
|||
|
-readdir_result_might_be_dir (struct readdir_result d)
|
|||
|
-{
|
|||
|
- return d.type == DT_DIR || readdir_result_might_be_symlink (d);
|
|||
|
-}
|
|||
|
-# else /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
|
|||
|
-# define D_TYPE_TO_RESULT(source)
|
|||
|
-
|
|||
|
-/* If we do not have type information, symbolic links and directories
|
|||
|
- are always a possibility. */
|
|||
|
-
|
|||
|
-static bool
|
|||
|
-readdir_result_might_be_symlink (struct readdir_result d)
|
|||
|
+/* Initialize and return type member of struct readdir_result. */
|
|||
|
+static dirent_type
|
|||
|
+readdir_result_type (struct readdir_result d)
|
|||
|
{
|
|||
|
- return true;
|
|||
|
+#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
|||
|
+# define D_TYPE_TO_RESULT(source) (source)->d_type,
|
|||
|
+ return d.type;
|
|||
|
+#else
|
|||
|
+# define D_TYPE_TO_RESULT(source)
|
|||
|
+ return DT_UNKNOWN;
|
|||
|
+#endif
|
|||
|
}
|
|||
|
|
|||
|
+/* Initialize and return skip_entry member of struct readdir_result. */
|
|||
|
static bool
|
|||
|
-readdir_result_might_be_dir (struct readdir_result d)
|
|||
|
+readdir_result_skip_entry (struct readdir_result d)
|
|||
|
{
|
|||
|
- return true;
|
|||
|
-}
|
|||
|
-
|
|||
|
-# endif /* defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE */
|
|||
|
-
|
|||
|
-# if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__
|
|||
|
/* Initializer for skip_entry. POSIX does not require that the d_ino
|
|||
|
field be present, and some systems do not provide it. */
|
|||
|
-# define D_INO_TO_RESULT(source) false,
|
|||
|
-# else
|
|||
|
-# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
|
|||
|
-# endif
|
|||
|
+#if defined _LIBC || defined D_INO_IN_DIRENT
|
|||
|
+# define D_INO_TO_RESULT(source) (source)->d_ino == 0,
|
|||
|
+ return d.skip_entry;
|
|||
|
+#else
|
|||
|
+# define D_INO_TO_RESULT(source)
|
|||
|
+ return false;
|
|||
|
+#endif
|
|||
|
+}
|
|||
|
|
|||
|
/* Construct an initializer for a struct readdir_result object from a
|
|||
|
struct dirent *. No copy of the name is made. */
|
|||
|
@@ -186,8 +155,6 @@ readdir_result_might_be_dir (struct read
|
|||
|
D_INO_TO_RESULT (source) \
|
|||
|
}
|
|||
|
|
|||
|
-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
|
|||
|
-
|
|||
|
/* Call gl_readdir on STREAM. This macro can be overridden to reduce
|
|||
|
type safety if an old interface version needs to be supported. */
|
|||
|
#ifndef GL_READDIR
|
|||
|
@@ -225,18 +192,55 @@ convert_dirent64 (const struct dirent64
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
+#ifndef _LIBC
|
|||
|
+/* The results of opendir() in this file are not used with dirfd and fchdir,
|
|||
|
+ and we do not leak fds to any single-threaded code that could use stdio,
|
|||
|
+ therefore save some unnecessary recursion in fchdir.c and opendir_safer.c.
|
|||
|
+ FIXME - if the kernel ever adds support for multi-thread safety for
|
|||
|
+ avoiding standard fds, then we should use opendir_safer. */
|
|||
|
+# ifdef GNULIB_defined_opendir
|
|||
|
+# undef opendir
|
|||
|
+# endif
|
|||
|
+# ifdef GNULIB_defined_closedir
|
|||
|
+# undef closedir
|
|||
|
+# endif
|
|||
|
|
|||
|
-#ifndef attribute_hidden
|
|||
|
-# define attribute_hidden
|
|||
|
+/* Just use malloc. */
|
|||
|
+# define __libc_use_alloca(n) false
|
|||
|
+# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0)
|
|||
|
+# define extend_alloca_account(buf, len, newlen, avar) \
|
|||
|
+ ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
|
|||
|
#endif
|
|||
|
|
|||
|
+/* Set *R = A + B. Return true if the answer is mathematically
|
|||
|
+ incorrect due to overflow; in this case, *R is the low order
|
|||
|
+ bits of the correct answer. */
|
|||
|
+
|
|||
|
+static bool
|
|||
|
+size_add_wrapv (size_t a, size_t b, size_t *r)
|
|||
|
+{
|
|||
|
+#if 5 <= __GNUC__ && !defined __ICC
|
|||
|
+ return __builtin_add_overflow (a, b, r);
|
|||
|
+#else
|
|||
|
+ *r = a + b;
|
|||
|
+ return *r < a;
|
|||
|
+#endif
|
|||
|
+}
|
|||
|
+
|
|||
|
+static bool
|
|||
|
+glob_use_alloca (size_t alloca_used, size_t len)
|
|||
|
+{
|
|||
|
+ size_t size;
|
|||
|
+ return (!size_add_wrapv (alloca_used, len, &size)
|
|||
|
+ && __libc_use_alloca (size));
|
|||
|
+}
|
|||
|
+
|
|||
|
static int glob_in_dir (const char *pattern, const char *directory,
|
|||
|
int flags, int (*errfunc) (const char *, int),
|
|||
|
glob_t *pglob, size_t alloca_used);
|
|||
|
extern int __glob_pattern_type (const char *pattern, int quote)
|
|||
|
attribute_hidden;
|
|||
|
|
|||
|
-#if !defined _LIBC || !defined GLOB_ONLY_P
|
|||
|
static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL;
|
|||
|
static int collated_compare (const void *, const void *) __THROWNL;
|
|||
|
|
|||
|
@@ -265,16 +269,15 @@ next_brace_sub (const char *cp, int flag
|
|||
|
return *cp != '\0' ? cp : NULL;
|
|||
|
}
|
|||
|
|
|||
|
-#endif /* !defined _LIBC || !defined GLOB_ONLY_P */
|
|||
|
|
|||
|
/* Do glob searching for PATTERN, placing results in PGLOB.
|
|||
|
The bits defined above may be set in FLAGS.
|
|||
|
If a directory cannot be opened or read and ERRFUNC is not nil,
|
|||
|
it is called with the pathname that caused the error, and the
|
|||
|
- `errno' value from the failing call; if it returns non-zero
|
|||
|
- `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
|
|||
|
+ 'errno' value from the failing call; if it returns non-zero
|
|||
|
+ 'glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
|
|||
|
If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
|
|||
|
- Otherwise, `glob' returns zero. */
|
|||
|
+ Otherwise, 'glob' returns zero. */
|
|||
|
int
|
|||
|
#ifdef GLOB_ATTRIBUTE
|
|||
|
GLOB_ATTRIBUTE
|
|||
|
@@ -292,9 +295,7 @@ glob (const char *pattern, int flags, in
|
|||
|
int malloc_dirname = 0;
|
|||
|
glob_t dirs;
|
|||
|
int retval = 0;
|
|||
|
-#ifdef _LIBC
|
|||
|
size_t alloca_used = 0;
|
|||
|
-#endif
|
|||
|
|
|||
|
if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
|
|||
|
{
|
|||
|
@@ -308,7 +309,7 @@ glob (const char *pattern, int flags, in
|
|||
|
flags |= GLOB_ONLYDIR;
|
|||
|
|
|||
|
if (!(flags & GLOB_DOOFFS))
|
|||
|
- /* Have to do this so `globfree' knows where to start freeing. It
|
|||
|
+ /* Have to do this so 'globfree' knows where to start freeing. It
|
|||
|
also makes all the code that uses gl_offs simpler. */
|
|||
|
pglob->gl_offs = 0;
|
|||
|
|
|||
|
@@ -372,14 +373,12 @@ glob (const char *pattern, int flags, in
|
|||
|
size_t rest_len;
|
|||
|
char *onealt;
|
|||
|
size_t pattern_len = strlen (pattern) - 1;
|
|||
|
-#ifdef _LIBC
|
|||
|
- int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
|
|||
|
+ int alloca_onealt = glob_use_alloca (alloca_used, pattern_len);
|
|||
|
if (alloca_onealt)
|
|||
|
onealt = alloca_account (pattern_len, alloca_used);
|
|||
|
else
|
|||
|
-#endif
|
|||
|
{
|
|||
|
- onealt = (char *) malloc (pattern_len);
|
|||
|
+ onealt = malloc (pattern_len);
|
|||
|
if (onealt == NULL)
|
|||
|
return GLOB_NOSPACE;
|
|||
|
}
|
|||
|
@@ -392,11 +391,9 @@ glob (const char *pattern, int flags, in
|
|||
|
next = next_brace_sub (begin + 1, flags);
|
|||
|
if (next == NULL)
|
|||
|
{
|
|||
|
- /* It is an illegal expression. */
|
|||
|
+ /* It is an invalid expression. */
|
|||
|
illegal_brace:
|
|||
|
-#ifdef _LIBC
|
|||
|
if (__glibc_unlikely (!alloca_onealt))
|
|||
|
-#endif
|
|||
|
free (onealt);
|
|||
|
flags &= ~GLOB_BRACE;
|
|||
|
goto no_brace;
|
|||
|
@@ -437,9 +434,7 @@ glob (const char *pattern, int flags, in
|
|||
|
/* If we got an error, return it. */
|
|||
|
if (result && result != GLOB_NOMATCH)
|
|||
|
{
|
|||
|
-#ifdef _LIBC
|
|||
|
if (__glibc_unlikely (!alloca_onealt))
|
|||
|
-#endif
|
|||
|
free (onealt);
|
|||
|
if (!(flags & GLOB_APPEND))
|
|||
|
{
|
|||
|
@@ -458,9 +453,7 @@ glob (const char *pattern, int flags, in
|
|||
|
assert (next != NULL);
|
|||
|
}
|
|||
|
|
|||
|
-#ifdef _LIBC
|
|||
|
if (__glibc_unlikely (!alloca_onealt))
|
|||
|
-#endif
|
|||
|
free (onealt);
|
|||
|
|
|||
|
if (pglob->gl_pathc != firstc)
|
|||
|
@@ -476,14 +469,16 @@ glob (const char *pattern, int flags, in
|
|||
|
|
|||
|
/* Find the filename. */
|
|||
|
filename = strrchr (pattern, '/');
|
|||
|
+
|
|||
|
#if defined __MSDOS__ || defined WINDOWS32
|
|||
|
- /* The case of "d:pattern". Since `:' is not allowed in
|
|||
|
+ /* The case of "d:pattern". Since ':' is not allowed in
|
|||
|
file names, we can safely assume that wherever it
|
|||
|
happens in pattern, it signals the filename part. This
|
|||
|
is so we could some day support patterns like "[a-z]:foo". */
|
|||
|
if (filename == NULL)
|
|||
|
filename = strchr (pattern, ':');
|
|||
|
#endif /* __MSDOS__ || WINDOWS32 */
|
|||
|
+
|
|||
|
dirname_modified = 0;
|
|||
|
if (filename == NULL)
|
|||
|
{
|
|||
|
@@ -508,11 +503,7 @@ glob (const char *pattern, int flags, in
|
|||
|
}
|
|||
|
|
|||
|
filename = pattern;
|
|||
|
-#ifdef _AMIGA
|
|||
|
- dirname = (char *) "";
|
|||
|
-#else
|
|||
|
dirname = (char *) ".";
|
|||
|
-#endif
|
|||
|
dirlen = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
@@ -536,22 +527,21 @@ glob (const char *pattern, int flags, in
|
|||
|
char *drive_spec;
|
|||
|
|
|||
|
++dirlen;
|
|||
|
- drive_spec = (char *) __alloca (dirlen + 1);
|
|||
|
+ drive_spec = __alloca (dirlen + 1);
|
|||
|
*((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0';
|
|||
|
/* For now, disallow wildcards in the drive spec, to
|
|||
|
prevent infinite recursion in glob. */
|
|||
|
if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE)))
|
|||
|
return GLOB_NOMATCH;
|
|||
|
- /* If this is "d:pattern", we need to copy `:' to DIRNAME
|
|||
|
+ /* If this is "d:pattern", we need to copy ':' to DIRNAME
|
|||
|
as well. If it's "d:/pattern", don't remove the slash
|
|||
|
from "d:/", since "d:" and "d:/" are not the same.*/
|
|||
|
}
|
|||
|
#endif
|
|||
|
-#ifdef _LIBC
|
|||
|
- if (__libc_use_alloca (alloca_used + dirlen + 1))
|
|||
|
+
|
|||
|
+ if (glob_use_alloca (alloca_used, dirlen + 1))
|
|||
|
newp = alloca_account (dirlen + 1, alloca_used);
|
|||
|
else
|
|||
|
-#endif
|
|||
|
{
|
|||
|
newp = malloc (dirlen + 1);
|
|||
|
if (newp == NULL)
|
|||
|
@@ -562,14 +552,17 @@ glob (const char *pattern, int flags, in
|
|||
|
dirname = newp;
|
|||
|
++filename;
|
|||
|
|
|||
|
- if (filename[0] == '\0'
|
|||
|
#if defined __MSDOS__ || defined WINDOWS32
|
|||
|
- && dirname[dirlen - 1] != ':'
|
|||
|
- && (dirlen < 3 || dirname[dirlen - 2] != ':'
|
|||
|
- || dirname[dirlen - 1] != '/')
|
|||
|
+ bool drive_root = (dirlen > 1
|
|||
|
+ && (dirname[dirlen - 1] == ':'
|
|||
|
+ || (dirlen > 2 && dirname[dirlen - 2] == ':'
|
|||
|
+ && dirname[dirlen - 1] == '/')));
|
|||
|
+#else
|
|||
|
+ bool drive_root = false;
|
|||
|
#endif
|
|||
|
- && dirlen > 1)
|
|||
|
- /* "pattern/". Expand "pattern", appending slashes. */
|
|||
|
+
|
|||
|
+ if (filename[0] == '\0' && dirlen > 1 && !drive_root)
|
|||
|
+ /* "pattern/". Expand "pattern", appending slashes. */
|
|||
|
{
|
|||
|
int orig_flags = flags;
|
|||
|
if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\')
|
|||
|
@@ -602,7 +595,6 @@ glob (const char *pattern, int flags, in
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
-#ifndef VMS
|
|||
|
if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~')
|
|||
|
{
|
|||
|
if (dirname[1] == '\0' || dirname[1] == '/'
|
|||
|
@@ -612,100 +604,127 @@ glob (const char *pattern, int flags, in
|
|||
|
/* Look up home directory. */
|
|||
|
char *home_dir = getenv ("HOME");
|
|||
|
int malloc_home_dir = 0;
|
|||
|
-# ifdef _AMIGA
|
|||
|
- if (home_dir == NULL || home_dir[0] == '\0')
|
|||
|
- home_dir = "SYS:";
|
|||
|
-# else
|
|||
|
-# ifdef WINDOWS32
|
|||
|
- if (home_dir == NULL || home_dir[0] == '\0')
|
|||
|
- home_dir = "c:/users/default"; /* poor default */
|
|||
|
-# else
|
|||
|
if (home_dir == NULL || home_dir[0] == '\0')
|
|||
|
{
|
|||
|
+#ifdef WINDOWS32
|
|||
|
+ /* Windows NT defines HOMEDRIVE and HOMEPATH. But give
|
|||
|
+ preference to HOME, because the user can change HOME. */
|
|||
|
+ const char *home_drive = getenv ("HOMEDRIVE");
|
|||
|
+ const char *home_path = getenv ("HOMEPATH");
|
|||
|
+
|
|||
|
+ if (home_drive != NULL && home_path != NULL)
|
|||
|
+ {
|
|||
|
+ size_t home_drive_len = strlen (home_drive);
|
|||
|
+ size_t home_path_len = strlen (home_path);
|
|||
|
+ char *mem = alloca (home_drive_len + home_path_len + 1);
|
|||
|
+
|
|||
|
+ memcpy (mem, home_drive, home_drive_len);
|
|||
|
+ memcpy (mem + home_drive_len, home_path, home_path_len + 1);
|
|||
|
+ home_dir = mem;
|
|||
|
+ }
|
|||
|
+ else
|
|||
|
+ home_dir = "c:/users/default"; /* poor default */
|
|||
|
+#else
|
|||
|
int success;
|
|||
|
char *name;
|
|||
|
+ int malloc_name = 0;
|
|||
|
size_t buflen = GET_LOGIN_NAME_MAX () + 1;
|
|||
|
|
|||
|
if (buflen == 0)
|
|||
|
- /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try
|
|||
|
+ /* 'sysconf' does not support _SC_LOGIN_NAME_MAX. Try
|
|||
|
a moderate value. */
|
|||
|
buflen = 20;
|
|||
|
- name = alloca_account (buflen, alloca_used);
|
|||
|
+ if (glob_use_alloca (alloca_used, buflen))
|
|||
|
+ name = alloca_account (buflen, alloca_used);
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ name = malloc (buflen);
|
|||
|
+ if (name == NULL)
|
|||
|
+ {
|
|||
|
+ retval = GLOB_NOSPACE;
|
|||
|
+ goto out;
|
|||
|
+ }
|
|||
|
+ malloc_name = 1;
|
|||
|
+ }
|
|||
|
|
|||
|
success = __getlogin_r (name, buflen) == 0;
|
|||
|
if (success)
|
|||
|
{
|
|||
|
struct passwd *p;
|
|||
|
-# if defined HAVE_GETPWNAM_R || defined _LIBC
|
|||
|
- long int pwbuflen = GETPW_R_SIZE_MAX ();
|
|||
|
+ char *malloc_pwtmpbuf = NULL;
|
|||
|
char *pwtmpbuf;
|
|||
|
+# if defined HAVE_GETPWNAM_R || defined _LIBC
|
|||
|
+ long int pwbuflenmax = GETPW_R_SIZE_MAX ();
|
|||
|
+ size_t pwbuflen = pwbuflenmax;
|
|||
|
struct passwd pwbuf;
|
|||
|
- int malloc_pwtmpbuf = 0;
|
|||
|
int save = errno;
|
|||
|
|
|||
|
-# ifndef _LIBC
|
|||
|
- if (pwbuflen == -1)
|
|||
|
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX.
|
|||
|
+# ifndef _LIBC
|
|||
|
+ if (! (0 < pwbuflenmax && pwbuflenmax <= SIZE_MAX))
|
|||
|
+ /* 'sysconf' does not support _SC_GETPW_R_SIZE_MAX.
|
|||
|
Try a moderate value. */
|
|||
|
pwbuflen = 1024;
|
|||
|
-# endif
|
|||
|
- if (__libc_use_alloca (alloca_used + pwbuflen))
|
|||
|
+# endif
|
|||
|
+ if (glob_use_alloca (alloca_used, pwbuflen))
|
|||
|
pwtmpbuf = alloca_account (pwbuflen, alloca_used);
|
|||
|
else
|
|||
|
{
|
|||
|
pwtmpbuf = malloc (pwbuflen);
|
|||
|
if (pwtmpbuf == NULL)
|
|||
|
{
|
|||
|
+ if (__glibc_unlikely (malloc_name))
|
|||
|
+ free (name);
|
|||
|
retval = GLOB_NOSPACE;
|
|||
|
goto out;
|
|||
|
}
|
|||
|
- malloc_pwtmpbuf = 1;
|
|||
|
+ malloc_pwtmpbuf = pwtmpbuf;
|
|||
|
}
|
|||
|
|
|||
|
while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
|
|||
|
!= 0)
|
|||
|
{
|
|||
|
+ size_t newlen;
|
|||
|
+ bool v;
|
|||
|
if (errno != ERANGE)
|
|||
|
{
|
|||
|
p = NULL;
|
|||
|
break;
|
|||
|
}
|
|||
|
-
|
|||
|
- if (!malloc_pwtmpbuf
|
|||
|
- && __libc_use_alloca (alloca_used
|
|||
|
- + 2 * pwbuflen))
|
|||
|
+ v = size_add_wrapv (pwbuflen, pwbuflen, &newlen);
|
|||
|
+ if (!v && malloc_pwtmpbuf == NULL
|
|||
|
+ && glob_use_alloca (alloca_used, newlen))
|
|||
|
pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
|
|||
|
- 2 * pwbuflen,
|
|||
|
- alloca_used);
|
|||
|
+ newlen, alloca_used);
|
|||
|
else
|
|||
|
{
|
|||
|
- char *newp = realloc (malloc_pwtmpbuf
|
|||
|
- ? pwtmpbuf : NULL,
|
|||
|
- 2 * pwbuflen);
|
|||
|
+ char *newp = (v ? NULL
|
|||
|
+ : realloc (malloc_pwtmpbuf, newlen));
|
|||
|
if (newp == NULL)
|
|||
|
{
|
|||
|
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
|||
|
- free (pwtmpbuf);
|
|||
|
+ free (malloc_pwtmpbuf);
|
|||
|
+ if (__glibc_unlikely (malloc_name))
|
|||
|
+ free (name);
|
|||
|
retval = GLOB_NOSPACE;
|
|||
|
goto out;
|
|||
|
}
|
|||
|
- pwtmpbuf = newp;
|
|||
|
- pwbuflen = 2 * pwbuflen;
|
|||
|
- malloc_pwtmpbuf = 1;
|
|||
|
+ malloc_pwtmpbuf = pwtmpbuf = newp;
|
|||
|
}
|
|||
|
+ pwbuflen = newlen;
|
|||
|
__set_errno (save);
|
|||
|
}
|
|||
|
-# else
|
|||
|
+# else
|
|||
|
p = getpwnam (name);
|
|||
|
-# endif
|
|||
|
+# endif
|
|||
|
+ if (__glibc_unlikely (malloc_name))
|
|||
|
+ free (name);
|
|||
|
if (p != NULL)
|
|||
|
{
|
|||
|
- if (!malloc_pwtmpbuf)
|
|||
|
+ if (malloc_pwtmpbuf == NULL)
|
|||
|
home_dir = p->pw_dir;
|
|||
|
else
|
|||
|
{
|
|||
|
size_t home_dir_len = strlen (p->pw_dir) + 1;
|
|||
|
- if (__libc_use_alloca (alloca_used + home_dir_len))
|
|||
|
+ if (glob_use_alloca (alloca_used, home_dir_len))
|
|||
|
home_dir = alloca_account (home_dir_len,
|
|||
|
alloca_used);
|
|||
|
else
|
|||
|
@@ -720,26 +739,32 @@ glob (const char *pattern, int flags, in
|
|||
|
malloc_home_dir = 1;
|
|||
|
}
|
|||
|
memcpy (home_dir, p->pw_dir, home_dir_len);
|
|||
|
-
|
|||
|
- free (pwtmpbuf);
|
|||
|
}
|
|||
|
}
|
|||
|
+ free (malloc_pwtmpbuf);
|
|||
|
}
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ if (__glibc_unlikely (malloc_name))
|
|||
|
+ free (name);
|
|||
|
+ }
|
|||
|
+#endif /* WINDOWS32 */
|
|||
|
}
|
|||
|
if (home_dir == NULL || home_dir[0] == '\0')
|
|||
|
{
|
|||
|
+ if (__glibc_unlikely (malloc_home_dir))
|
|||
|
+ free (home_dir);
|
|||
|
if (flags & GLOB_TILDE_CHECK)
|
|||
|
{
|
|||
|
- if (__glibc_unlikely (malloc_home_dir))
|
|||
|
- free (home_dir);
|
|||
|
retval = GLOB_NOMATCH;
|
|||
|
goto out;
|
|||
|
}
|
|||
|
else
|
|||
|
- home_dir = (char *) "~"; /* No luck. */
|
|||
|
+ {
|
|||
|
+ home_dir = (char *) "~"; /* No luck. */
|
|||
|
+ malloc_home_dir = 0;
|
|||
|
+ }
|
|||
|
}
|
|||
|
-# endif /* WINDOWS32 */
|
|||
|
-# endif
|
|||
|
/* Now construct the full directory. */
|
|||
|
if (dirname[1] == '\0')
|
|||
|
{
|
|||
|
@@ -754,8 +779,7 @@ glob (const char *pattern, int flags, in
|
|||
|
{
|
|||
|
char *newp;
|
|||
|
size_t home_len = strlen (home_dir);
|
|||
|
- int use_alloca = __libc_use_alloca (alloca_used
|
|||
|
- + home_len + dirlen);
|
|||
|
+ int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen);
|
|||
|
if (use_alloca)
|
|||
|
newp = alloca_account (home_len + dirlen, alloca_used);
|
|||
|
else
|
|||
|
@@ -779,12 +803,15 @@ glob (const char *pattern, int flags, in
|
|||
|
dirname = newp;
|
|||
|
dirlen += home_len - 1;
|
|||
|
malloc_dirname = !use_alloca;
|
|||
|
+
|
|||
|
+ if (__glibc_unlikely (malloc_home_dir))
|
|||
|
+ free (home_dir);
|
|||
|
}
|
|||
|
dirname_modified = 1;
|
|||
|
}
|
|||
|
-# if !defined _AMIGA && !defined WINDOWS32
|
|||
|
else
|
|||
|
{
|
|||
|
+#ifndef WINDOWS32
|
|||
|
char *end_name = strchr (dirname, '/');
|
|||
|
char *user_name;
|
|||
|
int malloc_user_name = 0;
|
|||
|
@@ -806,7 +833,7 @@ glob (const char *pattern, int flags, in
|
|||
|
else
|
|||
|
{
|
|||
|
char *newp;
|
|||
|
- if (__libc_use_alloca (alloca_used + (end_name - dirname)))
|
|||
|
+ if (glob_use_alloca (alloca_used, end_name - dirname))
|
|||
|
newp = alloca_account (end_name - dirname, alloca_used);
|
|||
|
else
|
|||
|
{
|
|||
|
@@ -823,11 +850,11 @@ glob (const char *pattern, int flags, in
|
|||
|
char *p = mempcpy (newp, dirname + 1,
|
|||
|
unescape - dirname - 1);
|
|||
|
char *q = unescape;
|
|||
|
- while (*q != '\0')
|
|||
|
+ while (q != end_name)
|
|||
|
{
|
|||
|
if (*q == '\\')
|
|||
|
{
|
|||
|
- if (q[1] == '\0')
|
|||
|
+ if (q + 1 == end_name)
|
|||
|
{
|
|||
|
/* "~fo\\o\\" unescape to user_name "foo\\",
|
|||
|
but "~fo\\o\\/" unescape to user_name
|
|||
|
@@ -843,7 +870,7 @@ glob (const char *pattern, int flags, in
|
|||
|
*p = '\0';
|
|||
|
}
|
|||
|
else
|
|||
|
- *((char *) mempcpy (newp, dirname + 1, end_name - dirname))
|
|||
|
+ *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1))
|
|||
|
= '\0';
|
|||
|
user_name = newp;
|
|||
|
}
|
|||
|
@@ -851,20 +878,21 @@ glob (const char *pattern, int flags, in
|
|||
|
/* Look up specific user's home directory. */
|
|||
|
{
|
|||
|
struct passwd *p;
|
|||
|
+ char *malloc_pwtmpbuf = NULL;
|
|||
|
# if defined HAVE_GETPWNAM_R || defined _LIBC
|
|||
|
- long int buflen = GETPW_R_SIZE_MAX ();
|
|||
|
+ long int buflenmax = GETPW_R_SIZE_MAX ();
|
|||
|
+ size_t buflen = buflenmax;
|
|||
|
char *pwtmpbuf;
|
|||
|
- int malloc_pwtmpbuf = 0;
|
|||
|
struct passwd pwbuf;
|
|||
|
int save = errno;
|
|||
|
|
|||
|
# ifndef _LIBC
|
|||
|
- if (buflen == -1)
|
|||
|
- /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
|
|||
|
+ if (! (0 <= buflenmax && buflenmax <= SIZE_MAX))
|
|||
|
+ /* Perhaps 'sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a
|
|||
|
moderate value. */
|
|||
|
buflen = 1024;
|
|||
|
# endif
|
|||
|
- if (__libc_use_alloca (alloca_used + buflen))
|
|||
|
+ if (glob_use_alloca (alloca_used, buflen))
|
|||
|
pwtmpbuf = alloca_account (buflen, alloca_used);
|
|||
|
else
|
|||
|
{
|
|||
|
@@ -877,32 +905,32 @@ glob (const char *pattern, int flags, in
|
|||
|
retval = GLOB_NOSPACE;
|
|||
|
goto out;
|
|||
|
}
|
|||
|
- malloc_pwtmpbuf = 1;
|
|||
|
+ malloc_pwtmpbuf = pwtmpbuf;
|
|||
|
}
|
|||
|
|
|||
|
while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
|
|||
|
{
|
|||
|
+ size_t newlen;
|
|||
|
+ bool v;
|
|||
|
if (errno != ERANGE)
|
|||
|
{
|
|||
|
p = NULL;
|
|||
|
break;
|
|||
|
}
|
|||
|
- if (!malloc_pwtmpbuf
|
|||
|
- && __libc_use_alloca (alloca_used + 2 * buflen))
|
|||
|
+ v = size_add_wrapv (buflen, buflen, &newlen);
|
|||
|
+ if (!v && malloc_pwtmpbuf == NULL
|
|||
|
+ && glob_use_alloca (alloca_used, newlen))
|
|||
|
pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
|
|||
|
- 2 * buflen, alloca_used);
|
|||
|
+ newlen, alloca_used);
|
|||
|
else
|
|||
|
{
|
|||
|
- char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
|
|||
|
- 2 * buflen);
|
|||
|
+ char *newp = v ? NULL : realloc (malloc_pwtmpbuf, newlen);
|
|||
|
if (newp == NULL)
|
|||
|
{
|
|||
|
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
|||
|
- free (pwtmpbuf);
|
|||
|
+ free (malloc_pwtmpbuf);
|
|||
|
goto nomem_getpw;
|
|||
|
}
|
|||
|
- pwtmpbuf = newp;
|
|||
|
- malloc_pwtmpbuf = 1;
|
|||
|
+ malloc_pwtmpbuf = pwtmpbuf = newp;
|
|||
|
}
|
|||
|
__set_errno (save);
|
|||
|
}
|
|||
|
@@ -923,7 +951,7 @@ glob (const char *pattern, int flags, in
|
|||
|
free (dirname);
|
|||
|
malloc_dirname = 0;
|
|||
|
|
|||
|
- if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
|
|||
|
+ if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
|
|||
|
dirname = alloca_account (home_len + rest_len + 1,
|
|||
|
alloca_used);
|
|||
|
else
|
|||
|
@@ -931,8 +959,7 @@ glob (const char *pattern, int flags, in
|
|||
|
dirname = malloc (home_len + rest_len + 1);
|
|||
|
if (dirname == NULL)
|
|||
|
{
|
|||
|
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
|||
|
- free (pwtmpbuf);
|
|||
|
+ free (malloc_pwtmpbuf);
|
|||
|
retval = GLOB_NOSPACE;
|
|||
|
goto out;
|
|||
|
}
|
|||
|
@@ -944,24 +971,24 @@ glob (const char *pattern, int flags, in
|
|||
|
dirlen = home_len + rest_len;
|
|||
|
dirname_modified = 1;
|
|||
|
|
|||
|
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
|||
|
- free (pwtmpbuf);
|
|||
|
+ free (malloc_pwtmpbuf);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
- if (__glibc_unlikely (malloc_pwtmpbuf))
|
|||
|
- free (pwtmpbuf);
|
|||
|
+ free (malloc_pwtmpbuf);
|
|||
|
|
|||
|
if (flags & GLOB_TILDE_CHECK)
|
|||
|
- /* We have to regard it as an error if we cannot find the
|
|||
|
- home directory. */
|
|||
|
- return GLOB_NOMATCH;
|
|||
|
+ {
|
|||
|
+ /* We have to regard it as an error if we cannot find the
|
|||
|
+ home directory. */
|
|||
|
+ retval = GLOB_NOMATCH;
|
|||
|
+ goto out;
|
|||
|
+ }
|
|||
|
}
|
|||
|
}
|
|||
|
+#endif /* !WINDOWS32 */
|
|||
|
}
|
|||
|
-# endif /* Not Amiga && not WINDOWS32. */
|
|||
|
}
|
|||
|
-#endif /* Not VMS. */
|
|||
|
|
|||
|
/* Now test whether we looked for "~" or "~NAME". In this case we
|
|||
|
can give the answer now. */
|
|||
|
@@ -980,19 +1007,18 @@ glob (const char *pattern, int flags, in
|
|||
|
size_t newcount = pglob->gl_pathc + pglob->gl_offs;
|
|||
|
char **new_gl_pathv;
|
|||
|
|
|||
|
- if (newcount > UINTPTR_MAX - (1 + 1)
|
|||
|
- || newcount + 1 + 1 > ~((size_t) 0) / sizeof (char *))
|
|||
|
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
|
|||
|
{
|
|||
|
nospace:
|
|||
|
free (pglob->gl_pathv);
|
|||
|
pglob->gl_pathv = NULL;
|
|||
|
pglob->gl_pathc = 0;
|
|||
|
- return GLOB_NOSPACE;
|
|||
|
+ retval = GLOB_NOSPACE;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
|
|||
|
- new_gl_pathv
|
|||
|
- = (char **) realloc (pglob->gl_pathv,
|
|||
|
- (newcount + 1 + 1) * sizeof (char *));
|
|||
|
+ new_gl_pathv = realloc (pglob->gl_pathv,
|
|||
|
+ (newcount + 2) * sizeof (char *));
|
|||
|
if (new_gl_pathv == NULL)
|
|||
|
goto nospace;
|
|||
|
pglob->gl_pathv = new_gl_pathv;
|
|||
|
@@ -1006,12 +1032,19 @@ glob (const char *pattern, int flags, in
|
|||
|
p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen);
|
|||
|
p[0] = '/';
|
|||
|
p[1] = '\0';
|
|||
|
+ if (__glibc_unlikely (malloc_dirname))
|
|||
|
+ free (dirname);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
- pglob->gl_pathv[newcount] = strdup (dirname);
|
|||
|
- if (pglob->gl_pathv[newcount] == NULL)
|
|||
|
- goto nospace;
|
|||
|
+ if (__glibc_unlikely (malloc_dirname))
|
|||
|
+ pglob->gl_pathv[newcount] = dirname;
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ pglob->gl_pathv[newcount] = strdup (dirname);
|
|||
|
+ if (pglob->gl_pathv[newcount] == NULL)
|
|||
|
+ goto nospace;
|
|||
|
+ }
|
|||
|
}
|
|||
|
pglob->gl_pathv[++newcount] = NULL;
|
|||
|
++pglob->gl_pathc;
|
|||
|
@@ -1021,7 +1054,8 @@ glob (const char *pattern, int flags, in
|
|||
|
}
|
|||
|
|
|||
|
/* Not found. */
|
|||
|
- return GLOB_NOMATCH;
|
|||
|
+ retval = GLOB_NOMATCH;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
|
|||
|
meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE));
|
|||
|
@@ -1067,7 +1101,10 @@ glob (const char *pattern, int flags, in
|
|||
|
if (status != 0)
|
|||
|
{
|
|||
|
if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
|
|||
|
- return status;
|
|||
|
+ {
|
|||
|
+ retval = status;
|
|||
|
+ goto out;
|
|||
|
+ }
|
|||
|
goto no_matches;
|
|||
|
}
|
|||
|
|
|||
|
@@ -1078,19 +1115,6 @@ glob (const char *pattern, int flags, in
|
|||
|
{
|
|||
|
size_t old_pathc;
|
|||
|
|
|||
|
-#ifdef SHELL
|
|||
|
- {
|
|||
|
- /* Make globbing interruptible in the bash shell. */
|
|||
|
- extern int interrupt_state;
|
|||
|
-
|
|||
|
- if (interrupt_state)
|
|||
|
- {
|
|||
|
- globfree (&dirs);
|
|||
|
- return GLOB_ABORTED;
|
|||
|
- }
|
|||
|
- }
|
|||
|
-#endif /* SHELL. */
|
|||
|
-
|
|||
|
old_pathc = pglob->gl_pathc;
|
|||
|
status = glob_in_dir (filename, dirs.gl_pathv[i],
|
|||
|
((flags | GLOB_APPEND)
|
|||
|
@@ -1105,7 +1129,8 @@ glob (const char *pattern, int flags, in
|
|||
|
globfree (&dirs);
|
|||
|
globfree (pglob);
|
|||
|
pglob->gl_pathc = 0;
|
|||
|
- return status;
|
|||
|
+ retval = status;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
|
|||
|
/* Stick the directory on the front of each name. */
|
|||
|
@@ -1116,13 +1141,14 @@ glob (const char *pattern, int flags, in
|
|||
|
globfree (&dirs);
|
|||
|
globfree (pglob);
|
|||
|
pglob->gl_pathc = 0;
|
|||
|
- return GLOB_NOSPACE;
|
|||
|
+ retval = GLOB_NOSPACE;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
flags |= GLOB_MAGCHAR;
|
|||
|
|
|||
|
- /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls.
|
|||
|
+ /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls.
|
|||
|
But if we have not found any matching entry and the GLOB_NOCHECK
|
|||
|
flag was set we must return the input pattern itself. */
|
|||
|
if (pglob->gl_pathc + pglob->gl_offs == oldcount)
|
|||
|
@@ -1134,28 +1160,28 @@ glob (const char *pattern, int flags, in
|
|||
|
size_t newcount = pglob->gl_pathc + pglob->gl_offs;
|
|||
|
char **new_gl_pathv;
|
|||
|
|
|||
|
- if (newcount > UINTPTR_MAX - 2
|
|||
|
- || newcount + 2 > ~((size_t) 0) / sizeof (char *))
|
|||
|
+ if (newcount > SIZE_MAX / sizeof (char *) - 2)
|
|||
|
{
|
|||
|
nospace2:
|
|||
|
globfree (&dirs);
|
|||
|
- return GLOB_NOSPACE;
|
|||
|
+ retval = GLOB_NOSPACE;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
|
|||
|
- new_gl_pathv = (char **) realloc (pglob->gl_pathv,
|
|||
|
- (newcount + 2)
|
|||
|
- * sizeof (char *));
|
|||
|
+ new_gl_pathv = realloc (pglob->gl_pathv,
|
|||
|
+ (newcount + 2) * sizeof (char *));
|
|||
|
if (new_gl_pathv == NULL)
|
|||
|
goto nospace2;
|
|||
|
pglob->gl_pathv = new_gl_pathv;
|
|||
|
|
|||
|
- pglob->gl_pathv[newcount] = __strdup (pattern);
|
|||
|
+ pglob->gl_pathv[newcount] = strdup (pattern);
|
|||
|
if (pglob->gl_pathv[newcount] == NULL)
|
|||
|
{
|
|||
|
globfree (&dirs);
|
|||
|
globfree (pglob);
|
|||
|
pglob->gl_pathc = 0;
|
|||
|
- return GLOB_NOSPACE;
|
|||
|
+ retval = GLOB_NOSPACE;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
|
|||
|
++pglob->gl_pathc;
|
|||
|
@@ -1167,7 +1193,8 @@ glob (const char *pattern, int flags, in
|
|||
|
else
|
|||
|
{
|
|||
|
globfree (&dirs);
|
|||
|
- return GLOB_NOMATCH;
|
|||
|
+ retval = GLOB_NOMATCH;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@@ -1213,7 +1240,8 @@ glob (const char *pattern, int flags, in
|
|||
|
flags = orig_flags;
|
|||
|
goto no_matches;
|
|||
|
}
|
|||
|
- return status;
|
|||
|
+ retval = status;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
|
|||
|
if (dirlen > 0)
|
|||
|
@@ -1225,7 +1253,8 @@ glob (const char *pattern, int flags, in
|
|||
|
{
|
|||
|
globfree (pglob);
|
|||
|
pglob->gl_pathc = 0;
|
|||
|
- return GLOB_NOSPACE;
|
|||
|
+ retval = GLOB_NOSPACE;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
@@ -1250,7 +1279,8 @@ glob (const char *pattern, int flags, in
|
|||
|
{
|
|||
|
globfree (pglob);
|
|||
|
pglob->gl_pathc = 0;
|
|||
|
- return GLOB_NOSPACE;
|
|||
|
+ retval = GLOB_NOSPACE;
|
|||
|
+ goto out;
|
|||
|
}
|
|||
|
strcpy (&new[len - 2], "/");
|
|||
|
pglob->gl_pathv[i] = new;
|
|||
|
@@ -1276,32 +1306,12 @@ libc_hidden_def (glob)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
-#if !defined _LIBC || !defined GLOB_ONLY_P
|
|||
|
-
|
|||
|
-/* Free storage allocated in PGLOB by a previous `glob' call. */
|
|||
|
-void
|
|||
|
-globfree (glob_t *pglob)
|
|||
|
-{
|
|||
|
- if (pglob->gl_pathv != NULL)
|
|||
|
- {
|
|||
|
- size_t i;
|
|||
|
- for (i = 0; i < pglob->gl_pathc; ++i)
|
|||
|
- free (pglob->gl_pathv[pglob->gl_offs + i]);
|
|||
|
- free (pglob->gl_pathv);
|
|||
|
- pglob->gl_pathv = NULL;
|
|||
|
- }
|
|||
|
-}
|
|||
|
-#if defined _LIBC && !defined globfree
|
|||
|
-libc_hidden_def (globfree)
|
|||
|
-#endif
|
|||
|
-
|
|||
|
-
|
|||
|
/* Do a collated comparison of A and B. */
|
|||
|
static int
|
|||
|
collated_compare (const void *a, const void *b)
|
|||
|
{
|
|||
|
- const char *const s1 = *(const char *const * const) a;
|
|||
|
- const char *const s2 = *(const char *const * const) b;
|
|||
|
+ char *const *ps1 = a; char *s1 = *ps1;
|
|||
|
+ char *const *ps2 = b; char *s2 = *ps2;
|
|||
|
|
|||
|
if (s1 == s2)
|
|||
|
return 0;
|
|||
|
@@ -1322,28 +1332,24 @@ prefix_array (const char *dirname, char
|
|||
|
{
|
|||
|
size_t i;
|
|||
|
size_t dirlen = strlen (dirname);
|
|||
|
-#if defined __MSDOS__ || defined WINDOWS32
|
|||
|
- int sep_char = '/';
|
|||
|
-# define DIRSEP_CHAR sep_char
|
|||
|
-#else
|
|||
|
-# define DIRSEP_CHAR '/'
|
|||
|
-#endif
|
|||
|
+ char dirsep_char = '/';
|
|||
|
|
|||
|
if (dirlen == 1 && dirname[0] == '/')
|
|||
|
/* DIRNAME is just "/", so normal prepending would get us "//foo".
|
|||
|
We want "/foo" instead, so don't prepend any chars from DIRNAME. */
|
|||
|
dirlen = 0;
|
|||
|
+
|
|||
|
#if defined __MSDOS__ || defined WINDOWS32
|
|||
|
- else if (dirlen > 1)
|
|||
|
+ if (dirlen > 1)
|
|||
|
{
|
|||
|
if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
|
|||
|
/* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */
|
|||
|
--dirlen;
|
|||
|
else if (dirname[dirlen - 1] == ':')
|
|||
|
{
|
|||
|
- /* DIRNAME is "d:". Use `:' instead of `/'. */
|
|||
|
+ /* DIRNAME is "d:". Use ':' instead of '/'. */
|
|||
|
--dirlen;
|
|||
|
- sep_char = ':';
|
|||
|
+ dirsep_char = ':';
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
@@ -1351,7 +1357,7 @@ prefix_array (const char *dirname, char
|
|||
|
for (i = 0; i < n; ++i)
|
|||
|
{
|
|||
|
size_t eltlen = strlen (array[i]) + 1;
|
|||
|
- char *new = (char *) malloc (dirlen + 1 + eltlen);
|
|||
|
+ char *new = malloc (dirlen + 1 + eltlen);
|
|||
|
if (new == NULL)
|
|||
|
{
|
|||
|
while (i > 0)
|
|||
|
@@ -1361,7 +1367,7 @@ prefix_array (const char *dirname, char
|
|||
|
|
|||
|
{
|
|||
|
char *endp = mempcpy (new, dirname, dirlen);
|
|||
|
- *endp++ = DIRSEP_CHAR;
|
|||
|
+ *endp++ = dirsep_char;
|
|||
|
mempcpy (endp, array[i], eltlen);
|
|||
|
}
|
|||
|
free (array[i]);
|
|||
|
@@ -1371,103 +1377,57 @@ prefix_array (const char *dirname, char
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
-
|
|||
|
-/* We must not compile this function twice. */
|
|||
|
-#if !defined _LIBC || !defined NO_GLOB_PATTERN_P
|
|||
|
-int
|
|||
|
-__glob_pattern_type (const char *pattern, int quote)
|
|||
|
-{
|
|||
|
- const char *p;
|
|||
|
- int ret = 0;
|
|||
|
-
|
|||
|
- for (p = pattern; *p != '\0'; ++p)
|
|||
|
- switch (*p)
|
|||
|
- {
|
|||
|
- case '?':
|
|||
|
- case '*':
|
|||
|
- return 1;
|
|||
|
-
|
|||
|
- case '\\':
|
|||
|
- if (quote)
|
|||
|
- {
|
|||
|
- if (p[1] != '\0')
|
|||
|
- ++p;
|
|||
|
- ret |= 2;
|
|||
|
- }
|
|||
|
- break;
|
|||
|
-
|
|||
|
- case '[':
|
|||
|
- ret |= 4;
|
|||
|
- break;
|
|||
|
-
|
|||
|
- case ']':
|
|||
|
- if (ret & 4)
|
|||
|
- return 1;
|
|||
|
- break;
|
|||
|
- }
|
|||
|
-
|
|||
|
- return ret;
|
|||
|
-}
|
|||
|
-
|
|||
|
-/* Return nonzero if PATTERN contains any metacharacters.
|
|||
|
- Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
|
|||
|
-int
|
|||
|
-__glob_pattern_p (const char *pattern, int quote)
|
|||
|
-{
|
|||
|
- return __glob_pattern_type (pattern, quote) == 1;
|
|||
|
-}
|
|||
|
-# ifdef _LIBC
|
|||
|
-weak_alias (__glob_pattern_p, glob_pattern_p)
|
|||
|
-# endif
|
|||
|
-#endif
|
|||
|
-
|
|||
|
-#endif /* !GLOB_ONLY_P */
|
|||
|
-
|
|||
|
-
|
|||
|
/* We put this in a separate function mainly to allow the memory
|
|||
|
allocated with alloca to be recycled. */
|
|||
|
-#if !defined _LIBC || !defined GLOB_ONLY_P
|
|||
|
static int
|
|||
|
__attribute_noinline__
|
|||
|
-link_exists2_p (const char *dir, size_t dirlen, const char *fname,
|
|||
|
- glob_t *pglob
|
|||
|
-# ifndef _LIBC
|
|||
|
- , int flags
|
|||
|
+link_stat (const char *dir, size_t dirlen, const char *fname,
|
|||
|
+ glob_t *pglob
|
|||
|
+# if !defined _LIBC && !HAVE_FSTATAT
|
|||
|
+ , int flags
|
|||
|
# endif
|
|||
|
- )
|
|||
|
+ )
|
|||
|
{
|
|||
|
size_t fnamelen = strlen (fname);
|
|||
|
- char *fullname = (char *) __alloca (dirlen + 1 + fnamelen + 1);
|
|||
|
+ char *fullname = __alloca (dirlen + 1 + fnamelen + 1);
|
|||
|
struct stat st;
|
|||
|
-# ifndef _LIBC
|
|||
|
- struct_stat64 st64;
|
|||
|
-# endif
|
|||
|
|
|||
|
mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1),
|
|||
|
fname, fnamelen + 1);
|
|||
|
|
|||
|
-# ifdef _LIBC
|
|||
|
- return (*pglob->gl_stat) (fullname, &st) == 0;
|
|||
|
-# else
|
|||
|
- return ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
|
|||
|
- ? (*pglob->gl_stat) (fullname, &st)
|
|||
|
- : __stat64 (fullname, &st64)) == 0);
|
|||
|
+# if !defined _LIBC && !HAVE_FSTATAT
|
|||
|
+ if (__builtin_expect ((flags & GLOB_ALTDIRFUNC) == 0, 1))
|
|||
|
+ {
|
|||
|
+ struct_stat64 st64;
|
|||
|
+ return __stat64 (fullname, &st64);
|
|||
|
+ }
|
|||
|
# endif
|
|||
|
+ return (*pglob->gl_stat) (fullname, &st);
|
|||
|
}
|
|||
|
-# ifdef _LIBC
|
|||
|
-# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
|
|||
|
- (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) \
|
|||
|
- ? link_exists2_p (dirname, dirnamelen, fname, pglob) \
|
|||
|
- : ({ struct stat64 st64; \
|
|||
|
- __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0) == 0; }))
|
|||
|
+
|
|||
|
+/* Return true if DIR/FNAME exists. */
|
|||
|
+static int
|
|||
|
+link_exists_p (int dfd, const char *dir, size_t dirlen, const char *fname,
|
|||
|
+ glob_t *pglob, int flags)
|
|||
|
+{
|
|||
|
+ int status;
|
|||
|
+# if defined _LIBC || HAVE_FSTATAT
|
|||
|
+ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0))
|
|||
|
+ status = link_stat (dir, dirlen, fname, pglob);
|
|||
|
+ else
|
|||
|
+ {
|
|||
|
+ /* dfd cannot be -1 here, because dirfd never returns -1 on
|
|||
|
+ glibc, or on hosts that have fstatat. */
|
|||
|
+ struct_stat64 st64;
|
|||
|
+ status = __fxstatat64 (_STAT_VER, dfd, fname, &st64, 0);
|
|||
|
+ }
|
|||
|
# else
|
|||
|
-# define link_exists_p(dfd, dirname, dirnamelen, fname, pglob, flags) \
|
|||
|
- link_exists2_p (dirname, dirnamelen, fname, pglob, flags)
|
|||
|
+ status = link_stat (dir, dirlen, fname, pglob, flags);
|
|||
|
# endif
|
|||
|
-#endif
|
|||
|
-
|
|||
|
+ return status == 0 || errno == EOVERFLOW;
|
|||
|
+}
|
|||
|
|
|||
|
-/* Like `glob', but PATTERN is a final pathname component,
|
|||
|
+/* Like 'glob', but PATTERN is a final pathname component,
|
|||
|
and matches are searched for in DIRECTORY.
|
|||
|
The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done.
|
|||
|
The GLOB_APPEND flag is assumed to be set (always appends). */
|
|||
|
@@ -1478,25 +1438,25 @@ glob_in_dir (const char *pattern, const
|
|||
|
{
|
|||
|
size_t dirlen = strlen (directory);
|
|||
|
void *stream = NULL;
|
|||
|
- struct globnames
|
|||
|
- {
|
|||
|
- struct globnames *next;
|
|||
|
- size_t count;
|
|||
|
- char *name[64];
|
|||
|
- };
|
|||
|
-#define INITIAL_COUNT sizeof (init_names.name) / sizeof (init_names.name[0])
|
|||
|
- struct globnames init_names;
|
|||
|
- struct globnames *names = &init_names;
|
|||
|
- struct globnames *names_alloca = &init_names;
|
|||
|
+# define GLOBNAMES_MEMBERS(nnames) \
|
|||
|
+ struct globnames *next; size_t count; char *name[nnames];
|
|||
|
+ struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
|
|||
|
+ struct { GLOBNAMES_MEMBERS (64) } init_names_buf;
|
|||
|
+ struct globnames *init_names = (struct globnames *) &init_names_buf;
|
|||
|
+ struct globnames *names = init_names;
|
|||
|
+ struct globnames *names_alloca = init_names;
|
|||
|
size_t nfound = 0;
|
|||
|
size_t cur = 0;
|
|||
|
int meta;
|
|||
|
int save;
|
|||
|
+ int result;
|
|||
|
|
|||
|
- alloca_used += sizeof (init_names);
|
|||
|
+ alloca_used += sizeof init_names_buf;
|
|||
|
|
|||
|
- init_names.next = NULL;
|
|||
|
- init_names.count = INITIAL_COUNT;
|
|||
|
+ init_names->next = NULL;
|
|||
|
+ init_names->count = ((sizeof init_names_buf
|
|||
|
+ - offsetof (struct globnames, name))
|
|||
|
+ / sizeof init_names->name[0]);
|
|||
|
|
|||
|
meta = __glob_pattern_type (pattern, !(flags & GLOB_NOESCAPE));
|
|||
|
if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
|
|||
|
@@ -1516,14 +1476,16 @@ glob_in_dir (const char *pattern, const
|
|||
|
struct_stat64 st64;
|
|||
|
} ust;
|
|||
|
size_t patlen = strlen (pattern);
|
|||
|
- int alloca_fullname = __libc_use_alloca (alloca_used
|
|||
|
- + dirlen + 1 + patlen + 1);
|
|||
|
+ size_t fullsize;
|
|||
|
+ bool alloca_fullname
|
|||
|
+ = (! size_add_wrapv (dirlen + 1, patlen + 1, &fullsize)
|
|||
|
+ && glob_use_alloca (alloca_used, fullsize));
|
|||
|
char *fullname;
|
|||
|
if (alloca_fullname)
|
|||
|
- fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
|
|||
|
+ fullname = alloca_account (fullsize, alloca_used);
|
|||
|
else
|
|||
|
{
|
|||
|
- fullname = malloc (dirlen + 1 + patlen + 1);
|
|||
|
+ fullname = malloc (fullsize);
|
|||
|
if (fullname == NULL)
|
|||
|
return GLOB_NOSPACE;
|
|||
|
}
|
|||
|
@@ -1531,9 +1493,11 @@ glob_in_dir (const char *pattern, const
|
|||
|
mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
|
|||
|
"/", 1),
|
|||
|
pattern, patlen + 1);
|
|||
|
- if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
|
|||
|
+ if (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
|
|||
|
? (*pglob->gl_stat) (fullname, &ust.st)
|
|||
|
- : __stat64 (fullname, &ust.st64)) == 0)
|
|||
|
+ : __stat64 (fullname, &ust.st64))
|
|||
|
+ == 0)
|
|||
|
+ || errno == EOVERFLOW)
|
|||
|
/* We found this file to be existing. Now tell the rest
|
|||
|
of the function to copy this name into the result. */
|
|||
|
flags |= GLOB_NOCHECK;
|
|||
|
@@ -1555,16 +1519,10 @@ glob_in_dir (const char *pattern, const
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
-#ifdef _LIBC
|
|||
|
int dfd = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
|
|||
|
? -1 : dirfd ((DIR *) stream));
|
|||
|
-#endif
|
|||
|
int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
|
|||
|
- | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
|
|||
|
-#if defined _AMIGA || defined VMS
|
|||
|
- | FNM_CASEFOLD
|
|||
|
-#endif
|
|||
|
- );
|
|||
|
+ | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
|
|||
|
flags |= GLOB_MAGCHAR;
|
|||
|
|
|||
|
while (1)
|
|||
|
@@ -1584,19 +1542,24 @@ glob_in_dir (const char *pattern, const
|
|||
|
}
|
|||
|
if (d.name == NULL)
|
|||
|
break;
|
|||
|
- if (d.skip_entry)
|
|||
|
+ if (readdir_result_skip_entry (d))
|
|||
|
continue;
|
|||
|
|
|||
|
/* If we shall match only directories use the information
|
|||
|
provided by the dirent call if possible. */
|
|||
|
- if ((flags & GLOB_ONLYDIR) && !readdir_result_might_be_dir (d))
|
|||
|
- continue;
|
|||
|
+ if (flags & GLOB_ONLYDIR)
|
|||
|
+ switch (readdir_result_type (d))
|
|||
|
+ {
|
|||
|
+ case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
|
|||
|
+ default: continue;
|
|||
|
+ }
|
|||
|
|
|||
|
if (fnmatch (pattern, d.name, fnm_flags) == 0)
|
|||
|
{
|
|||
|
/* If the file we found is a symlink we have to
|
|||
|
make sure the target file exists. */
|
|||
|
- if (!readdir_result_might_be_symlink (d)
|
|||
|
+ dirent_type type = readdir_result_type (d);
|
|||
|
+ if (! (type == DT_LNK || type == DT_UNKNOWN)
|
|||
|
|| link_exists_p (dfd, directory, dirlen, d.name,
|
|||
|
pglob, flags))
|
|||
|
{
|
|||
|
@@ -1604,10 +1567,13 @@ glob_in_dir (const char *pattern, const
|
|||
|
{
|
|||
|
struct globnames *newnames;
|
|||
|
size_t count = names->count * 2;
|
|||
|
- size_t size = (sizeof (struct globnames)
|
|||
|
- + ((count - INITIAL_COUNT)
|
|||
|
- * sizeof (char *)));
|
|||
|
- if (__libc_use_alloca (alloca_used + size))
|
|||
|
+ size_t nameoff = offsetof (struct globnames, name);
|
|||
|
+ size_t size = FLEXSIZEOF (struct globnames, name,
|
|||
|
+ count * sizeof (char *));
|
|||
|
+ if ((SIZE_MAX - nameoff) / 2 / sizeof (char *)
|
|||
|
+ < names->count)
|
|||
|
+ goto memory_error;
|
|||
|
+ if (glob_use_alloca (alloca_used, size))
|
|||
|
newnames = names_alloca
|
|||
|
= alloca_account (size, alloca_used);
|
|||
|
else if ((newnames = malloc (size))
|
|||
|
@@ -1623,6 +1589,8 @@ glob_in_dir (const char *pattern, const
|
|||
|
goto memory_error;
|
|||
|
++cur;
|
|||
|
++nfound;
|
|||
|
+ if (SIZE_MAX - pglob->gl_offs <= nfound)
|
|||
|
+ goto memory_error;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
@@ -1633,29 +1601,27 @@ glob_in_dir (const char *pattern, const
|
|||
|
{
|
|||
|
size_t len = strlen (pattern);
|
|||
|
nfound = 1;
|
|||
|
- names->name[cur] = (char *) malloc (len + 1);
|
|||
|
+ names->name[cur] = malloc (len + 1);
|
|||
|
if (names->name[cur] == NULL)
|
|||
|
goto memory_error;
|
|||
|
*((char *) mempcpy (names->name[cur++], pattern, len)) = '\0';
|
|||
|
}
|
|||
|
|
|||
|
- int result = GLOB_NOMATCH;
|
|||
|
+ result = GLOB_NOMATCH;
|
|||
|
if (nfound != 0)
|
|||
|
{
|
|||
|
+ char **new_gl_pathv;
|
|||
|
result = 0;
|
|||
|
|
|||
|
- if (pglob->gl_pathc > UINTPTR_MAX - pglob->gl_offs
|
|||
|
- || pglob->gl_pathc + pglob->gl_offs > UINTPTR_MAX - nfound
|
|||
|
- || pglob->gl_pathc + pglob->gl_offs + nfound > UINTPTR_MAX - 1
|
|||
|
- || (pglob->gl_pathc + pglob->gl_offs + nfound + 1
|
|||
|
- > UINTPTR_MAX / sizeof (char *)))
|
|||
|
+ if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc
|
|||
|
+ < pglob->gl_offs + nfound + 1)
|
|||
|
goto memory_error;
|
|||
|
|
|||
|
- char **new_gl_pathv;
|
|||
|
new_gl_pathv
|
|||
|
- = (char **) realloc (pglob->gl_pathv,
|
|||
|
- (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
|
|||
|
- * sizeof (char *));
|
|||
|
+ = realloc (pglob->gl_pathv,
|
|||
|
+ (pglob->gl_pathc + pglob->gl_offs + nfound + 1)
|
|||
|
+ * sizeof (char *));
|
|||
|
+
|
|||
|
if (new_gl_pathv == NULL)
|
|||
|
{
|
|||
|
memory_error:
|
|||
|
@@ -1671,7 +1637,7 @@ glob_in_dir (const char *pattern, const
|
|||
|
and this is the block assigned to OLD here. */
|
|||
|
if (names == NULL)
|
|||
|
{
|
|||
|
- assert (old == &init_names);
|
|||
|
+ assert (old == init_names);
|
|||
|
break;
|
|||
|
}
|
|||
|
cur = names->count;
|
|||
|
@@ -1697,7 +1663,7 @@ glob_in_dir (const char *pattern, const
|
|||
|
and this is the block assigned to OLD here. */
|
|||
|
if (names == NULL)
|
|||
|
{
|
|||
|
- assert (old == &init_names);
|
|||
|
+ assert (old == init_names);
|
|||
|
break;
|
|||
|
}
|
|||
|
cur = names->count;
|
|||
|
Index: glibc-2.26/posix/glob64.c
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/posix/glob64.c
|
|||
|
+++ glibc-2.26/posix/glob64.c
|
|||
|
@@ -43,10 +43,4 @@ glob64 (const char *pattern, int flags,
|
|||
|
}
|
|||
|
libc_hidden_def (glob64)
|
|||
|
|
|||
|
-void
|
|||
|
-globfree64 (glob64_t *pglob)
|
|||
|
-{
|
|||
|
-}
|
|||
|
-libc_hidden_def (globfree64)
|
|||
|
-
|
|||
|
stub_warning (glob64)
|
|||
|
Index: glibc-2.26/posix/glob_internal.h
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/posix/glob_internal.h
|
|||
|
@@ -0,0 +1,57 @@
|
|||
|
+/* Shared definition for glob and glob_pattern_p.
|
|||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
|||
|
+ This file is part of the GNU C Library.
|
|||
|
+
|
|||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|||
|
+ modify it under the terms of the GNU Lesser General Public
|
|||
|
+ License as published by the Free Software Foundation; either
|
|||
|
+ version 2.1 of the License, or (at your option) any later version.
|
|||
|
+
|
|||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ Lesser General Public License for more details.
|
|||
|
+
|
|||
|
+ You should have received a copy of the GNU Lesser General Public
|
|||
|
+ License along with the GNU C Library; if not, see
|
|||
|
+ <http://www.gnu.org/licenses/>. */
|
|||
|
+
|
|||
|
+#ifndef GLOB_INTERNAL_H
|
|||
|
+# define GLOB_INTERNAL_H
|
|||
|
+
|
|||
|
+static inline int
|
|||
|
+__glob_pattern_type (const char *pattern, int quote)
|
|||
|
+{
|
|||
|
+ const char *p;
|
|||
|
+ int ret = 0;
|
|||
|
+
|
|||
|
+ for (p = pattern; *p != '\0'; ++p)
|
|||
|
+ switch (*p)
|
|||
|
+ {
|
|||
|
+ case '?':
|
|||
|
+ case '*':
|
|||
|
+ return 1;
|
|||
|
+
|
|||
|
+ case '\\':
|
|||
|
+ if (quote)
|
|||
|
+ {
|
|||
|
+ if (p[1] != '\0')
|
|||
|
+ ++p;
|
|||
|
+ ret |= 2;
|
|||
|
+ }
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ case '[':
|
|||
|
+ ret |= 4;
|
|||
|
+ break;
|
|||
|
+
|
|||
|
+ case ']':
|
|||
|
+ if (ret & 4)
|
|||
|
+ return 1;
|
|||
|
+ break;
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ return ret;
|
|||
|
+}
|
|||
|
+
|
|||
|
+#endif /* GLOB_INTERNAL_H */
|
|||
|
Index: glibc-2.26/posix/glob_pattern_p.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/posix/glob_pattern_p.c
|
|||
|
@@ -0,0 +1,33 @@
|
|||
|
+/* Return nonzero if PATTERN contains any metacharacters.
|
|||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
|||
|
+ This file is part of the GNU C Library.
|
|||
|
+
|
|||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|||
|
+ modify it under the terms of the GNU Lesser General Public
|
|||
|
+ License as published by the Free Software Foundation; either
|
|||
|
+ version 2.1 of the License, or (at your option) any later version.
|
|||
|
+
|
|||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ Lesser General Public License for more details.
|
|||
|
+
|
|||
|
+ You should have received a copy of the GNU Lesser General Public
|
|||
|
+ License along with the GNU C Library; if not, see
|
|||
|
+ <http://www.gnu.org/licenses/>. */
|
|||
|
+
|
|||
|
+#ifndef _LIBC
|
|||
|
+# include <config.h>
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+#include <glob.h>
|
|||
|
+#include "glob_internal.h"
|
|||
|
+
|
|||
|
+/* Return nonzero if PATTERN contains any metacharacters.
|
|||
|
+ Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
|
|||
|
+int
|
|||
|
+__glob_pattern_p (const char *pattern, int quote)
|
|||
|
+{
|
|||
|
+ return __glob_pattern_type (pattern, quote) == 1;
|
|||
|
+}
|
|||
|
+weak_alias (__glob_pattern_p, glob_pattern_p)
|
|||
|
Index: glibc-2.26/posix/globfree.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/posix/globfree.c
|
|||
|
@@ -0,0 +1,41 @@
|
|||
|
+/* Frees the dynamically allocated storage from an earlier call to glob.
|
|||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
|||
|
+ This file is part of the GNU C Library.
|
|||
|
+
|
|||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|||
|
+ modify it under the terms of the GNU Lesser General Public
|
|||
|
+ License as published by the Free Software Foundation; either
|
|||
|
+ version 2.1 of the License, or (at your option) any later version.
|
|||
|
+
|
|||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ Lesser General Public License for more details.
|
|||
|
+
|
|||
|
+ You should have received a copy of the GNU Lesser General Public
|
|||
|
+ License along with the GNU C Library; if not, see
|
|||
|
+ <http://www.gnu.org/licenses/>. */
|
|||
|
+
|
|||
|
+#ifndef _LIBC
|
|||
|
+# include <config.h>
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+#include <glob.h>
|
|||
|
+#include <stdlib.h>
|
|||
|
+
|
|||
|
+/* Free storage allocated in PGLOB by a previous `glob' call. */
|
|||
|
+void
|
|||
|
+globfree (glob_t *pglob)
|
|||
|
+{
|
|||
|
+ if (pglob->gl_pathv != NULL)
|
|||
|
+ {
|
|||
|
+ size_t i;
|
|||
|
+ for (i = 0; i < pglob->gl_pathc; ++i)
|
|||
|
+ free (pglob->gl_pathv[pglob->gl_offs + i]);
|
|||
|
+ free (pglob->gl_pathv);
|
|||
|
+ pglob->gl_pathv = NULL;
|
|||
|
+ }
|
|||
|
+}
|
|||
|
+#ifndef globfree
|
|||
|
+libc_hidden_def (globfree)
|
|||
|
+#endif
|
|||
|
Index: glibc-2.26/posix/globfree64.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/posix/globfree64.c
|
|||
|
@@ -0,0 +1,31 @@
|
|||
|
+/* Frees the dynamically allocated storage from an earlier call to glob.
|
|||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
|||
|
+ This file is part of the GNU C Library.
|
|||
|
+
|
|||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|||
|
+ modify it under the terms of the GNU Lesser General Public
|
|||
|
+ License as published by the Free Software Foundation; either
|
|||
|
+ version 2.1 of the License, or (at your option) any later version.
|
|||
|
+
|
|||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ Lesser General Public License for more details.
|
|||
|
+
|
|||
|
+ You should have received a copy of the GNU Lesser General Public
|
|||
|
+ License along with the GNU C Library; if not, see
|
|||
|
+ <http://www.gnu.org/licenses/>. */
|
|||
|
+
|
|||
|
+#ifndef _LIBC
|
|||
|
+# include <config.h>
|
|||
|
+#endif
|
|||
|
+
|
|||
|
+#include <glob.h>
|
|||
|
+#include <stdlib.h>
|
|||
|
+
|
|||
|
+/* Free storage allocated in PGLOB by a previous `glob' call. */
|
|||
|
+void
|
|||
|
+globfree64 (glob64_t *pglob)
|
|||
|
+{
|
|||
|
+}
|
|||
|
+libc_hidden_def (globfree64)
|
|||
|
Index: glibc-2.26/posix/tst-glob-tilde.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/posix/tst-glob-tilde.c
|
|||
|
@@ -0,0 +1,136 @@
|
|||
|
+/* Check for GLOB_TIDLE heap allocation issues (bug 22320, bug 22325).
|
|||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
|||
|
+ This file is part of the GNU C Library.
|
|||
|
+
|
|||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|||
|
+ modify it under the terms of the GNU Lesser General Public
|
|||
|
+ License as published by the Free Software Foundation; either
|
|||
|
+ version 2.1 of the License, or (at your option) any later version.
|
|||
|
+
|
|||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ Lesser General Public License for more details.
|
|||
|
+
|
|||
|
+ You should have received a copy of the GNU Lesser General Public
|
|||
|
+ License along with the GNU C Library; if not, see
|
|||
|
+ <http://www.gnu.org/licenses/>. */
|
|||
|
+
|
|||
|
+#include <glob.h>
|
|||
|
+#include <mcheck.h>
|
|||
|
+#include <nss.h>
|
|||
|
+#include <pwd.h>
|
|||
|
+#include <stdlib.h>
|
|||
|
+#include <string.h>
|
|||
|
+#include <support/check.h>
|
|||
|
+#include <support/support.h>
|
|||
|
+
|
|||
|
+/* Flag which indicates whether to pass the GLOB_ONLYDIR flag. */
|
|||
|
+static int do_onlydir;
|
|||
|
+
|
|||
|
+/* Flag which indicates whether to pass the GLOB_NOCHECK flag. */
|
|||
|
+static int do_nocheck;
|
|||
|
+
|
|||
|
+/* Flag which indicates whether to pass the GLOB_MARK flag. */
|
|||
|
+static int do_mark;
|
|||
|
+
|
|||
|
+static void
|
|||
|
+one_test (const char *prefix, const char *middle, const char *suffix)
|
|||
|
+{
|
|||
|
+ char *pattern = xasprintf ("%s%s%s", prefix, middle, suffix);
|
|||
|
+ int flags = GLOB_TILDE;
|
|||
|
+ if (do_onlydir)
|
|||
|
+ flags |= GLOB_ONLYDIR;
|
|||
|
+ if (do_nocheck)
|
|||
|
+ flags |= GLOB_NOCHECK;
|
|||
|
+ if (do_mark)
|
|||
|
+ flags |= GLOB_MARK;
|
|||
|
+ glob_t gl;
|
|||
|
+ /* This glob call might result in crashes or memory leaks. */
|
|||
|
+ if (glob (pattern, flags, NULL, &gl) == 0)
|
|||
|
+ globfree (&gl);
|
|||
|
+ free (pattern);
|
|||
|
+}
|
|||
|
+
|
|||
|
+enum
|
|||
|
+ {
|
|||
|
+ /* The largest base being tested. */
|
|||
|
+ largest_base_size = 500000,
|
|||
|
+
|
|||
|
+ /* The actual size is the base size plus a variable whose absolute
|
|||
|
+ value is not greater than this. This helps malloc to trigger
|
|||
|
+ overflows. */
|
|||
|
+ max_size_skew = 16,
|
|||
|
+
|
|||
|
+ /* The maximum string length supported by repeating_string
|
|||
|
+ below. */
|
|||
|
+ repeat_size = largest_base_size + max_size_skew,
|
|||
|
+ };
|
|||
|
+
|
|||
|
+/* Used to construct strings which repeat a single character 'x'. */
|
|||
|
+static char *repeat;
|
|||
|
+
|
|||
|
+/* Return a string of SIZE characters. */
|
|||
|
+const char *
|
|||
|
+repeating_string (int size)
|
|||
|
+{
|
|||
|
+ TEST_VERIFY (size >= 0);
|
|||
|
+ TEST_VERIFY (size <= repeat_size);
|
|||
|
+ const char *repeated_shifted = repeat + repeat_size - size;
|
|||
|
+ TEST_VERIFY (strlen (repeated_shifted) == size);
|
|||
|
+ return repeated_shifted;
|
|||
|
+}
|
|||
|
+
|
|||
|
+static int
|
|||
|
+do_test (void)
|
|||
|
+{
|
|||
|
+ /* Avoid network-based NSS modules and initialize nss_files with a
|
|||
|
+ dummy lookup. This has to come before mtrace because NSS does
|
|||
|
+ not free all memory. */
|
|||
|
+ __nss_configure_lookup ("passwd", "files");
|
|||
|
+ (void) getpwnam ("root");
|
|||
|
+
|
|||
|
+ mtrace ();
|
|||
|
+
|
|||
|
+ repeat = xmalloc (repeat_size + 1);
|
|||
|
+ memset (repeat, 'x', repeat_size);
|
|||
|
+ repeat[repeat_size] = '\0';
|
|||
|
+
|
|||
|
+ /* These numbers control the size of the user name. The values
|
|||
|
+ cover the minimum (0), a typical size (8), a large
|
|||
|
+ stack-allocated size (100000), and a somewhat large
|
|||
|
+ heap-allocated size (largest_base_size). */
|
|||
|
+ static const int base_sizes[] = { 0, 8, 100, 100000, largest_base_size, -1 };
|
|||
|
+
|
|||
|
+ for (do_onlydir = 0; do_onlydir < 2; ++do_onlydir)
|
|||
|
+ for (do_nocheck = 0; do_nocheck < 2; ++do_nocheck)
|
|||
|
+ for (do_mark = 0; do_mark < 2; ++do_mark)
|
|||
|
+ for (int base_idx = 0; base_sizes[base_idx] >= 0; ++base_idx)
|
|||
|
+ {
|
|||
|
+ for (int size_skew = -max_size_skew; size_skew <= max_size_skew;
|
|||
|
+ ++size_skew)
|
|||
|
+ {
|
|||
|
+ int size = base_sizes[base_idx] + size_skew;
|
|||
|
+ if (size < 0)
|
|||
|
+ continue;
|
|||
|
+
|
|||
|
+ const char *user_name = repeating_string (size);
|
|||
|
+ one_test ("~", user_name, "/a/b");
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ const char *user_name = repeating_string (base_sizes[base_idx]);
|
|||
|
+ one_test ("~", user_name, "");
|
|||
|
+ one_test ("~", user_name, "/");
|
|||
|
+ one_test ("~", user_name, "/a");
|
|||
|
+ one_test ("~", user_name, "/*/*");
|
|||
|
+ one_test ("~", user_name, "\\/");
|
|||
|
+ one_test ("/~", user_name, "");
|
|||
|
+ one_test ("*/~", user_name, "/a/b");
|
|||
|
+ }
|
|||
|
+
|
|||
|
+ free (repeat);
|
|||
|
+
|
|||
|
+ return 0;
|
|||
|
+}
|
|||
|
+
|
|||
|
+#include <support/test-driver.c>
|
|||
|
Index: glibc-2.26/sysdeps/gnu/glob64.c
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/sysdeps/gnu/glob64.c
|
|||
|
+++ glibc-2.26/sysdeps/gnu/glob64.c
|
|||
|
@@ -15,11 +15,8 @@
|
|||
|
#undef __stat
|
|||
|
#define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
|
|||
|
|
|||
|
-#define NO_GLOB_PATTERN_P 1
|
|||
|
-
|
|||
|
#define COMPILE_GLOB64 1
|
|||
|
|
|||
|
#include <posix/glob.c>
|
|||
|
|
|||
|
libc_hidden_def (glob64)
|
|||
|
-libc_hidden_def (globfree64)
|
|||
|
Index: glibc-2.26/sysdeps/gnu/globfree64.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/gnu/globfree64.c
|
|||
|
@@ -0,0 +1,10 @@
|
|||
|
+#include <dirent.h>
|
|||
|
+#include <glob.h>
|
|||
|
+#include <sys/stat.h>
|
|||
|
+
|
|||
|
+#define glob_t glob64_t
|
|||
|
+#define globfree(pglob) globfree64 (pglob)
|
|||
|
+
|
|||
|
+#include <posix/globfree.c>
|
|||
|
+
|
|||
|
+libc_hidden_def (globfree64)
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/Makefile
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/sysdeps/unix/sysv/linux/Makefile
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/Makefile
|
|||
|
@@ -166,7 +166,7 @@ endif
|
|||
|
ifeq ($(subdir),posix)
|
|||
|
sysdep_headers += bits/initspin.h
|
|||
|
|
|||
|
-sysdep_routines += sched_getcpu
|
|||
|
+sysdep_routines += sched_getcpu oldglob
|
|||
|
|
|||
|
tests += tst-affinity tst-affinity-pid
|
|||
|
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/alpha/glob.c
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/sysdeps/unix/sysv/linux/alpha/glob.c
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/alpha/glob.c
|
|||
|
@@ -42,10 +42,6 @@ extern void __new_globfree (glob_t *__pg
|
|||
|
#undef globfree64
|
|||
|
|
|||
|
versioned_symbol (libc, __new_glob, glob, GLIBC_2_1);
|
|||
|
-versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1);
|
|||
|
libc_hidden_ver (__new_glob, glob)
|
|||
|
-libc_hidden_ver (__new_globfree, globfree)
|
|||
|
|
|||
|
weak_alias (__new_glob, glob64)
|
|||
|
-weak_alias (__new_globfree, globfree64)
|
|||
|
-libc_hidden_ver (__new_globfree, globfree64)
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/alpha/globfree.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/alpha/globfree.c
|
|||
|
@@ -0,0 +1,37 @@
|
|||
|
+/* Compat globfree. Linux/alpha version.
|
|||
|
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
|||
|
+ This file is part of the GNU C Library.
|
|||
|
+
|
|||
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|||
|
+ modify it under the terms of the GNU Lesser General Public
|
|||
|
+ License as published by the Free Software Foundation; either
|
|||
|
+ version 2.1 of the License, or (at your option) any later version.
|
|||
|
+
|
|||
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
+ Lesser General Public License for more details.
|
|||
|
+
|
|||
|
+ You should have received a copy of the GNU Lesser General Public
|
|||
|
+ License along with the GNU C Library. If not, see
|
|||
|
+ <http://www.gnu.org/licenses/>. */
|
|||
|
+
|
|||
|
+#define globfree64 __no_globfree64_decl
|
|||
|
+#include <sys/types.h>
|
|||
|
+#include <glob.h>
|
|||
|
+#include <shlib-compat.h>
|
|||
|
+
|
|||
|
+#define globfree(pglob) \
|
|||
|
+ __new_globfree (pglob)
|
|||
|
+
|
|||
|
+extern void __new_globfree (glob_t *__pglob);
|
|||
|
+
|
|||
|
+#include <posix/globfree.c>
|
|||
|
+
|
|||
|
+#undef globfree64
|
|||
|
+
|
|||
|
+versioned_symbol (libc, __new_globfree, globfree, GLIBC_2_1);
|
|||
|
+libc_hidden_ver (__new_globfree, globfree)
|
|||
|
+
|
|||
|
+weak_alias (__new_globfree, globfree64)
|
|||
|
+libc_hidden_ver (__new_globfree, globfree64)
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/i386/glob64.c
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/sysdeps/unix/sysv/linux/i386/glob64.c
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/i386/glob64.c
|
|||
|
@@ -19,6 +19,7 @@
|
|||
|
#include <dirent.h>
|
|||
|
#include <glob.h>
|
|||
|
#include <sys/stat.h>
|
|||
|
+#include <shlib-compat.h>
|
|||
|
|
|||
|
#define dirent dirent64
|
|||
|
#define __readdir(dirp) __readdir64 (dirp)
|
|||
|
@@ -33,44 +34,9 @@
|
|||
|
#undef __stat
|
|||
|
#define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
|
|||
|
|
|||
|
-#define NO_GLOB_PATTERN_P 1
|
|||
|
-
|
|||
|
#define COMPILE_GLOB64 1
|
|||
|
|
|||
|
#include <posix/glob.c>
|
|||
|
|
|||
|
-#include "shlib-compat.h"
|
|||
|
-
|
|||
|
-libc_hidden_def (globfree64)
|
|||
|
-
|
|||
|
versioned_symbol (libc, __glob64, glob64, GLIBC_2_2);
|
|||
|
libc_hidden_ver (__glob64, glob64)
|
|||
|
-
|
|||
|
-#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
|
|||
|
-
|
|||
|
-#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
|
|||
|
-
|
|||
|
-int __old_glob64 (const char *__pattern, int __flags,
|
|||
|
- int (*__errfunc) (const char *, int),
|
|||
|
- glob64_t *__pglob);
|
|||
|
-
|
|||
|
-#undef dirent
|
|||
|
-#define dirent __old_dirent64
|
|||
|
-#undef GL_READDIR
|
|||
|
-# define GL_READDIR(pglob, stream) \
|
|||
|
- ((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
|
|||
|
-#undef __readdir
|
|||
|
-#define __readdir(dirp) __old_readdir64 (dirp)
|
|||
|
-#undef glob
|
|||
|
-#define glob(pattern, flags, errfunc, pglob) \
|
|||
|
- __old_glob64 (pattern, flags, errfunc, pglob)
|
|||
|
-#define convert_dirent __old_convert_dirent
|
|||
|
-#define glob_in_dir __old_glob_in_dir
|
|||
|
-#define GLOB_ATTRIBUTE attribute_compat_text_section
|
|||
|
-
|
|||
|
-#define GLOB_ONLY_P 1
|
|||
|
-
|
|||
|
-#include <posix/glob.c>
|
|||
|
-
|
|||
|
-compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1);
|
|||
|
-#endif
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/mips/mips64/n64/globfree64.c
|
|||
|
@@ -0,0 +1 @@
|
|||
|
+/* glob64 is in globfree64.c */
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/oldglob.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/oldglob.c
|
|||
|
@@ -0,0 +1,42 @@
|
|||
|
+#include <shlib-compat.h>
|
|||
|
+
|
|||
|
+#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
|
|||
|
+
|
|||
|
+#include <dirent.h>
|
|||
|
+#include <glob.h>
|
|||
|
+#include <sys/stat.h>
|
|||
|
+
|
|||
|
+#include <sysdeps/unix/sysv/linux/i386/olddirent.h>
|
|||
|
+
|
|||
|
+int __old_glob64 (const char *__pattern, int __flags,
|
|||
|
+ int (*__errfunc) (const char *, int),
|
|||
|
+ glob64_t *__pglob);
|
|||
|
+libc_hidden_proto (__old_glob64);
|
|||
|
+
|
|||
|
+#define dirent __old_dirent64
|
|||
|
+#define GL_READDIR(pglob, stream) \
|
|||
|
+ ((struct __old_dirent64 *) (pglob)->gl_readdir (stream))
|
|||
|
+#undef __readdir
|
|||
|
+#define __readdir(dirp) __old_readdir64 (dirp)
|
|||
|
+
|
|||
|
+#define glob_t glob64_t
|
|||
|
+#define glob(pattern, flags, errfunc, pglob) \
|
|||
|
+ __old_glob64 (pattern, flags, errfunc, pglob)
|
|||
|
+#define globfree(pglob) globfree64(pglob)
|
|||
|
+
|
|||
|
+#define convert_dirent __old_convert_dirent
|
|||
|
+#define glob_in_dir __old_glob_in_dir
|
|||
|
+
|
|||
|
+#undef stat
|
|||
|
+#define stat stat64
|
|||
|
+#undef __stat
|
|||
|
+#define __stat(file, buf) __xstat64 (_STAT_VER, file, buf)
|
|||
|
+
|
|||
|
+#define GLOB_ATTRIBUTE attribute_compat_text_section
|
|||
|
+
|
|||
|
+#include <posix/glob.c>
|
|||
|
+
|
|||
|
+libc_hidden_def (__old_glob64);
|
|||
|
+
|
|||
|
+compat_symbol (libc, __old_glob64, glob64, GLIBC_2_1);
|
|||
|
+#endif
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/wordsize-64/globfree64.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/wordsize-64/globfree64.c
|
|||
|
@@ -0,0 +1,2 @@
|
|||
|
+/* This file is here so sysdeps/gnu/glob64.c doesn't take precedence. */
|
|||
|
+#include <sysdeps/wordsize-64/globfree64.c>
|
|||
|
Index: glibc-2.26/sysdeps/unix/sysv/linux/x86_64/x32/globfree.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/unix/sysv/linux/x86_64/x32/globfree.c
|
|||
|
@@ -0,0 +1 @@
|
|||
|
+#include <sysdeps/wordsize-64/globfree.c>
|
|||
|
Index: glibc-2.26/sysdeps/wordsize-64/glob.c
|
|||
|
===================================================================
|
|||
|
--- glibc-2.26.orig/sysdeps/wordsize-64/glob.c
|
|||
|
+++ glibc-2.26/sysdeps/wordsize-64/glob.c
|
|||
|
@@ -4,5 +4,3 @@
|
|||
|
#undef glob64
|
|||
|
#undef globfree64
|
|||
|
weak_alias (glob, glob64)
|
|||
|
-weak_alias (globfree, globfree64)
|
|||
|
-libc_hidden_ver (globfree, globfree64)
|
|||
|
Index: glibc-2.26/sysdeps/wordsize-64/globfree.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/wordsize-64/globfree.c
|
|||
|
@@ -0,0 +1,5 @@
|
|||
|
+#define globfree64 __no_globfree64_decl
|
|||
|
+#include <posix/globfree.c>
|
|||
|
+#undef globfree64
|
|||
|
+weak_alias (globfree, globfree64)
|
|||
|
+libc_hidden_ver (globfree, globfree64)
|
|||
|
Index: glibc-2.26/sysdeps/wordsize-64/globfree64.c
|
|||
|
===================================================================
|
|||
|
--- /dev/null
|
|||
|
+++ glibc-2.26/sysdeps/wordsize-64/globfree64.c
|
|||
|
@@ -0,0 +1 @@
|
|||
|
+/* globfree64 is in globfree.c */
|