diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2017-08-22 10:13:50 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-08-22 10:26:40 -0700 |
commit | f320c1ebec8a551bfd32d264371a1c4ab4c8f0d6 (patch) | |
tree | 3497ab4c61a980fe059d1bd75f683d1cf9deaeb9 /lib/glob.c | |
parent | b23000de1e47c7d580e0e220966dd1ee42a5e5bc (diff) | |
download | gnulib-f320c1ebec8a551bfd32d264371a1c4ab4c8f0d6.tar.gz |
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.
Diffstat (limited to 'lib/glob.c')
-rw-r--r-- | lib/glob.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/lib/glob.c b/lib/glob.c index d061017992..2a7cc87056 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -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; |