From b5e099566022dd7390afe58cf84e5b991683776c Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Fri, 22 Sep 2017 14:41:52 -0700
Subject: [PATCH] glob: add compat to not follow dangling symlinks

Merged from this proposed change to glibc:
https://sourceware.org/ml/libc-alpha/2017-09/msg00848.html
* lib/glob.c [_LIBC]: Include <shlib-compat.h>.
(__glob, GLOB_ATTRIBUTE) [!_LIBC]: New macros.
(glob_lstat): New function.
(GL_LSTAT, LSTAT64): New macros.
(glob): Rename to __glob and add versioned symbol to 2.27.
(glob_in_dir): Use glob_lstat.
---
 ChangeLog  | 12 +++++++++++
 lib/glob.c | 70 +++++++++++++++++++++++++++++++++++++++-----------------------
 2 files changed, 56 insertions(+), 26 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 82ecf539a..313d359a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2017-09-22  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+
+	glob: add compat to not follow dangling symlinks
+	Merged from this proposed change to glibc:
+	https://sourceware.org/ml/libc-alpha/2017-09/msg00848.html
+	* lib/glob.c [_LIBC]: Include <shlib-compat.h>.
+	(__glob, GLOB_ATTRIBUTE) [!_LIBC]: New macros.
+	(glob_lstat): New function.
+	(GL_LSTAT, LSTAT64): New macros.
+	(glob): Rename to __glob and add versioned symbol to 2.27.
+	(glob_in_dir): Use glob_lstat.
+
 2017-09-21  Paul Eggert  <eggert@cs.ucla.edu>
 
 	mktime: port to OpenVMS
diff --git a/lib/glob.c b/lib/glob.c
index 2a5e6642e..a9b519c2f 100644
--- a/lib/glob.c
+++ b/lib/glob.c
@@ -57,7 +57,9 @@
 # endif
 # define struct_stat64          struct stat64
 # define FLEXIBLE_ARRAY_MEMBER
+# include <shlib-compat.h>
 #else /* !_LIBC */
+# define __glob                 glob
 # define __getlogin_r(buf, len) getlogin_r (buf, len)
 # define __lstat64(fname, buf)  lstat (fname, buf)
 # define __stat64(fname, buf)   stat (fname, buf)
@@ -179,6 +181,29 @@ convert_dirent64 (const struct dirent64 *source)
     ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0)
 #endif
 
+static int
+glob_lstat (glob_t *pglob, int flags, const char *fullname)
+{
+/* Use on glob-lstat-compat.c to provide a compat symbol which does not
+   use lstat / gl_lstat.  */
+#ifdef GLOB_NO_LSTAT
+# define GL_LSTAT gl_stat
+# define LSTAT64 __stat64
+#else
+# define GL_LSTAT gl_lstat
+# define LSTAT64 __lstat64
+#endif
+
+  union
+  {
+    struct stat st;
+    struct_stat64 st64;
+  } ust;
+  return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
+          ? pglob->GL_LSTAT (fullname, &ust.st)
+          : LSTAT64 (fullname, &ust.st64));
+}
+
 /* 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.  */
@@ -248,6 +273,9 @@ next_brace_sub (const char *cp, int flags)
   return *cp != '\0' ? cp : NULL;
 }
 
+#ifndef GLOB_ATTRIBUTE
+# define GLOB_ATTRIBUTE
+#endif
 
 /* Do glob searching for PATTERN, placing results in PGLOB.
    The bits defined above may be set in FLAGS.
@@ -258,11 +286,9 @@ next_brace_sub (const char *cp, int flags)
    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
    Otherwise, 'glob' returns zero.  */
 int
-#ifdef GLOB_ATTRIBUTE
 GLOB_ATTRIBUTE
-#endif
-glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
-      glob_t *pglob)
+__glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+        glob_t *pglob)
 {
   const char *filename;
   char *dirname = NULL;
@@ -343,7 +369,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
       if (begin != NULL)
         {
           /* Allocate working buffer large enough for our work.  Note that
-             we have at least an opening and closing brace.  */
+            we have at least an opening and closing brace.  */
           size_t firstc;
           char *alt_start;
           const char *p;
@@ -406,9 +432,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
               /* Construct the new glob expression.  */
               mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len);
 
-              result = glob (onealt,
-                             ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
-                              | GLOB_APPEND), errfunc, pglob);
+              result = __glob (onealt,
+                               ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC))
+                                | GLOB_APPEND),
+                               errfunc, pglob);
 
               /* If we got an error, return it.  */
               if (result && result != GLOB_NOMATCH)
@@ -499,7 +526,6 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
     {
       char *newp;
       dirlen = filename - pattern;
-
 #if defined __MSDOS__ || defined WINDOWS32
       if (*filename == ':'
           || (filename > pattern + 1 && filename[-1] == ':'))
@@ -558,7 +584,7 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
                   flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
                 }
             }
-          int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
+          int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob);
           if (val == 0)
             pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK)
                                | (flags & GLOB_MARK));
@@ -932,11 +958,10 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
           dirs.gl_lstat = pglob->gl_lstat;
         }
 
-      status = glob (dirname,
-                     ((flags & (GLOB_ERR | GLOB_NOESCAPE
-                                | GLOB_ALTDIRFUNC))
-                      | GLOB_NOSORT | GLOB_ONLYDIR),
-                     errfunc, &dirs);
+      status = __glob (dirname,
+                       ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC))
+                        | GLOB_NOSORT | GLOB_ONLYDIR),
+                       errfunc, &dirs);
       if (status != 0)
         {
           if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH)
@@ -1134,8 +1159,9 @@ glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 
   return retval;
 }
-#if defined _LIBC && !defined glob
-libc_hidden_def (glob)
+#if defined _LIBC && !defined __glob
+versioned_symbol (libc, __glob, glob, GLIBC_2_27);
+libc_hidden_ver (__glob, glob)
 #endif
 
 
@@ -1251,11 +1277,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
     }
   else if (meta == GLOBPAT_NONE)
     {
-      union
-      {
-        struct stat st;
-        struct_stat64 st64;
-      } ust;
       size_t patlen = strlen (pattern);
       size_t fullsize;
       bool alloca_fullname
@@ -1274,10 +1295,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
                         "/", 1),
                pattern, patlen + 1);
-      if (((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
-            ? (*pglob->gl_lstat) (fullname, &ust.st)
-            : __lstat64 (fullname, &ust.st64))
-           == 0)
+      if (glob_lstat (pglob, flags, fullname) == 0
           || errno == EOVERFLOW)
         /* We found this file to be existing.  Now tell the rest
            of the function to copy this name into the result.  */
-- 
2.13.5

