]> Savannah Git Hosting - gnulib.git/commitdiff
glob: port to clang's Undefined Sanitizer
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 22 Aug 2017 17:13:50 +0000 (10:13 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 22 Aug 2017 17:26:40 +0000 (10:26 -0700)
Problem reported by Tim Rühsen in:
http://lists.gnu.org/archive/html/bug-gnulib/2017-08/msg00144.html
* lib/glob.c (FLEXIBLE_ARRAY_MEMBER) [_LIBC]: Define to empty.
(glob_in_dir): Do not rely on undefined behavior in accessing
struct members beyond their bounds.  Use a flexible array member
instead.

ChangeLog
lib/glob.c

index 98643535fe4c9833d40103b4e513cdc3dff11e2e..3753cb2a565307d96411905ed04f64b9f1f88c58 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2017-08-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       glob: port to clang's Undefined Sanitizer
+       Problem reported by Tim Rühsen in:
+       http://lists.gnu.org/archive/html/bug-gnulib/2017-08/msg00144.html
+       * lib/glob.c (FLEXIBLE_ARRAY_MEMBER) [_LIBC]: Define to empty.
+       (glob_in_dir): Do not rely on undefined behavior in accessing
+       struct members beyond their bounds.  Use a flexible array member
+       instead.
+
 2017-08-21  Paul Eggert  <eggert@cs.ucla.edu>
 
        vc-list-files: port to Solaris 10
index d0610179926bd50e09fb0bdce0d5992a76b317ab..2a7cc87056ed6dcfc401bef7362941743cca1ecc 100644 (file)
@@ -75,6 +75,7 @@
 #  define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf)
 # endif
 # define struct_stat64          struct stat64
+# define FLEXIBLE_ARRAY_MEMBER
 #else /* !_LIBC */
 # define __getlogin_r(buf, len) getlogin_r (buf, len)
 # define __stat64(fname, buf)   stat (fname, buf)
@@ -1590,25 +1591,25 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
 {
   size_t dirlen = strlen (directory);
   void *stream = NULL;
-  struct globnames
-    {
-      struct globnames *next;
-      size_t count;
-      char *name[64];
-    };
-  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 = sizeof init_names.name / sizeof init_names.name[0];
+  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)))
@@ -1789,7 +1790,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
                  and this is the block assigned to OLD here.  */
               if (names == NULL)
                 {
-                  assert (old == &init_names);
+                  assert (old == init_names);
                   break;
                 }
               cur = names->count;
@@ -1816,7 +1817,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
                  and this is the block assigned to OLD here.  */
               if (names == NULL)
                 {
-                  assert (old == &init_names);
+                  assert (old == init_names);
                   break;
                 }
               cur = names->count;