diff lib/fts.c @ 18403:4434607ac1ce

flexmember: port better to GCC + valgrind With a char[] flexible array member in a struct with nontrivial alignment, GCC-generated code can access past the end of the array, because GCC assumes there are padding bytes to get the struct aligned. So the common idiom of malloc (offsetof (struct s, m), n) does not properly allocate an n-byte trailing member, as malloc’s argument should be the next multiple of alignof (struct s). See GCC Bug#66661: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66661 Although C11 apparently permits this GCC optimization (i.e., there was a bug in Gnulib not in GCC), possibly this is a defect in C11. See the thread containing: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg00317.html * lib/flexmember.h: New file. * lib/fnmatch.c, lib/fts.c, lib/glob.c, lib/idcache.c: * lib/localename.c, lib/time_rz.c: Include flexmember.h. * lib/fnmatch_loop.c (struct patternlist): * lib/localename.c (struct hash_node): Use FLEXIBLE_ARRAY_MEMBER. * lib/fnmatch_loop.c (EXT): * lib/fts.c (fts_alloc): * lib/glob.c (glob_in_dir): * lib/idcache.c (getuser, getuidbyname, getgroup, getgidbyname): * lib/localename.c (gl_lock_define_initialized): * lib/time_rz.c (tzalloc): Use FLEXSIZEOF instead of offsetof. * m4/flexmember.m4 (AC_C_FLEXIBLE_ARRAY_MEMBER): Check that the size of the struct can be taken. * modules/flexmember (Files): Add lib/flexmember.h. * modules/fnmatch, modules/glob, modules/localename (Depends-on): Add flexmember.
author Paul Eggert <eggert@cs.ucla.edu>
date Wed, 07 Sep 2016 02:01:42 -0700
parents 7276fe79480b
children 12df2165ec1c
line wrap: on
line diff
--- a/lib/fts.c	Tue Sep 06 23:56:26 2016 -0700
+++ b/lib/fts.c	Wed Sep 07 02:01:42 2016 -0700
@@ -76,6 +76,7 @@
 /* FIXME - use fcntl(F_DUPFD_CLOEXEC)/openat(O_CLOEXEC) once they are
    supported.  */
 # include "cloexec.h"
+# include "flexmember.h"
 # include "openat.h"
 # include "same-inode.h"
 #endif
@@ -1925,17 +1926,7 @@
          * The file name is a variable length array.  Allocate the FTSENT
          * structure and the file name in one chunk.
          */
-        len = offsetof(FTSENT, fts_name) + namelen + 1;
-        /* Align the allocation size so that it works for FTSENT,
-           so that trailing padding may be referenced by direct access
-           to the flexible array members, without triggering undefined behavior
-           by accessing bytes beyond the heap allocation.  This implicit access
-           was seen for example with ISDOT() and GCC 5.1.1 at -O2.
-           Do not use alignof (FTSENT) here, since C11 prohibits
-           taking the alignment of a structure containing a flexible
-           array member.  */
-        len += alignof (max_align_t) - 1;
-        len &= ~ (alignof (max_align_t) - 1);
+        len = FLEXSIZEOF(FTSENT, fts_name, namelen + 1);
         if ((p = malloc(len)) == NULL)
                 return (NULL);