+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
# 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)
{
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)))
and this is the block assigned to OLD here. */
if (names == NULL)
{
- assert (old == &init_names);
+ assert (old == init_names);
break;
}
cur = names->count;
and this is the block assigned to OLD here. */
if (names == NULL)
{
- assert (old == &init_names);
+ assert (old == init_names);
break;
}
cur = names->count;