The trouble is that it is modifying pointers in place, but doing so via
"void *" types which alias the pointers passed in (which are typically
pointers to a struct.) The inline ext2fs_resize_mem() code may update
the pointer, but the caller is not required to reload the old value it
may have cached in a register, according to the type aliasing rules.
This is causing the caller to dereference the old pointer when compiled
with -O2, resulting in reproducible SEGV, on at least one ia64
configuration.
The compiler *is* required to reload if it sees an update to a dereferenced
char value, though, as chars are defined to alias anything; and memcpy()
is defined to operate on chars. So using memcpy() to copy the pointer
values is guaranteed to force the caller to reload. This has been
verified to fix the problem in practice.
Fixes Red Hat bug #161183.
+2005-06-27 Stephen Tweedie <sct@redhat.com>
+
+ * ext2fs.h (ext2fs_resize_mem): Fix C99 strict type aliasing
+ problems. Addresses Red Hat Bugzilla #161183.
+
2005-06-19 Theodore Ts'o <tytso@mit.edu>
* getsectsize.c (BLKSSZGET): Clean up test for when to manually
unsigned long size, void *ptr)
{
void *p;
- void **pp = (void **)ptr;
- p = realloc(*pp, size);
+ /* Use "memcpy" for pointer assignments here to avoid problems
+ * with C99 strict type aliasing rules. */
+ memcpy(&p, ptr, sizeof (p));
+ p = realloc(p, size);
if (!p)
return EXT2_ET_NO_MEMORY;
- *pp = p;
+ memcpy(ptr, &p, sizeof (p));
return 0;
}
#endif /* Custom memory routines */