+2011-09-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port --enable-checking=all to Fedora 14 x86.
+ * alloc.c (XMALLOC_OVERRUN_CHECK_OVERHEAD, XMALLOC_OVERRUN_CHECK_SIZE):
+ Move to lisp.h.
+ (xmalloc_put_size, xmalloc_get_size, overrun_check_malloc)
+ (overrun_check_realloc, overrun_check_free):
+ Use XMALLOC_OVERRUN_SIZE_SIZE, not sizeof (size_t).
+ That way, xmalloc returns a properly-aligned pointer even if
+ XMALLOC_OVERRUN_CHECK is defined. The old debugging code happened
+ to align OK on typical 64-bit hosts, but not on Fedora 14 x86.
+ * charset.c (syms_of_charset): Take XMALLOC_OVERRUN_CHECK_OVERHEAD
+ into account when calculating the initial malloc maximum.
+ * lisp.h (XMALLOC_OVERRUN_CHECK_OVERHEAD, XMALLOC_OVERRUN_CHECK_SIZE):
+ Move here from alloc.c, so that charset.c can use it too.
+ Properly align; the old code wasn't right for common 32-bit hosts
+ when configured with --enable-checking=all.
+ (XMALLOC_BASE_ALIGNMENT, COMMON_MULTIPLE, XMALLOC_HEADER_ALIGNMENT)
+ (XMALLOC_OVERRUN_SIZE_SIZE): New macros.
+
2011-09-29 Eli Zaretskii <eliz@gnu.org>
* sysdep.c (snprintf) [EOVERFLOW]: If EOVERFLOW is not defined,
xsignal (Qnil, Vmemory_signal_data);
}
-
-#ifndef XMALLOC_OVERRUN_CHECK
-#define XMALLOC_OVERRUN_CHECK_OVERHEAD 0
-#else
+#ifdef XMALLOC_OVERRUN_CHECK
/* Check for overrun in malloc'ed buffers by wrapping a header and trailer
- around each block.
-
- The header consists of 16 fixed bytes followed by sizeof (size_t) bytes
- containing the original block size in little-endian order,
- while the trailer consists of 16 fixed bytes.
-
- The header is used to detect whether this block has been allocated
- through these functions -- as it seems that some low-level libc
- functions may bypass the malloc hooks.
-*/
-
-
-#define XMALLOC_OVERRUN_CHECK_SIZE 16
-#define XMALLOC_OVERRUN_CHECK_OVERHEAD \
- (2 * XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t))
+ around each block. */
static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] =
{ '\x9a', '\x9b', '\xae', '\xaf',
xmalloc_put_size (unsigned char *ptr, size_t size)
{
int i;
- for (i = 0; i < sizeof (size_t); i++)
+ for (i = 0; i < XMALLOC_OVERRUN_SIZE_SIZE; i++)
{
- *--ptr = size & (1 << CHAR_BIT) - 1;
+ *--ptr = size & ((1 << CHAR_BIT) - 1);
size >>= CHAR_BIT;
}
}
{
size_t size = 0;
int i;
- ptr -= sizeof (size_t);
- for (i = 0; i < sizeof (size_t); i++)
+ ptr -= XMALLOC_OVERRUN_SIZE_SIZE;
+ for (i = 0; i < XMALLOC_OVERRUN_SIZE_SIZE; i++)
{
size <<= CHAR_BIT;
size += *ptr++;
if (val && check_depth == 1)
{
memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
- val += XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+ val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
xmalloc_put_size (val, size);
memcpy (val + size, xmalloc_overrun_check_trailer,
XMALLOC_OVERRUN_CHECK_SIZE);
if (val
&& check_depth == 1
&& memcmp (xmalloc_overrun_check_header,
- val - XMALLOC_OVERRUN_CHECK_SIZE - sizeof (size_t),
+ val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE,
XMALLOC_OVERRUN_CHECK_SIZE) == 0)
{
size_t osize = xmalloc_get_size (val);
XMALLOC_OVERRUN_CHECK_SIZE))
abort ();
memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE);
- val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
- memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t));
+ val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
+ memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE);
}
val = (unsigned char *) realloc ((POINTER_TYPE *)val, size + overhead);
if (val && check_depth == 1)
{
memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE);
- val += XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+ val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
xmalloc_put_size (val, size);
memcpy (val + size, xmalloc_overrun_check_trailer,
XMALLOC_OVERRUN_CHECK_SIZE);
if (val
&& check_depth == 1
&& memcmp (xmalloc_overrun_check_header,
- val - XMALLOC_OVERRUN_CHECK_SIZE - sizeof (size_t),
+ val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE,
XMALLOC_OVERRUN_CHECK_SIZE) == 0)
{
size_t osize = xmalloc_get_size (val);
XMALLOC_OVERRUN_CHECK_SIZE))
abort ();
#ifdef XMALLOC_CLEAR_FREE_MEMORY
- val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
+ val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD);
#else
memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE);
- val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t);
- memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t));
+ val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE;
+ memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE);
#endif
}
extern int immediate_quit; /* Nonzero means ^G can quit instantly */
+/* Overhead for overrun check in malloc'ed buffers. The check
+ operates by wrapping a header and trailer around each block.
+
+ The header consists of XMALLOC_OVERRUN_CHECK_SIZE fixed bytes
+ followed by XMALLOC_OVERRUN_SIZE_SIZE bytes containing the original
+ block size in little-endian order. The trailer consists of
+ XMALLOC_OVERRUN_CHECK_SIZE fixed bytes.
+
+ The header is used to detect whether this block has been allocated
+ through these functions, as some low-level libc functions may
+ bypass the malloc hooks. */
+
+#ifndef XMALLOC_OVERRUN_CHECK
+# define XMALLOC_OVERRUN_CHECK_OVERHEAD 0
+#else
+
+# define XMALLOC_OVERRUN_CHECK_SIZE 16
+# define XMALLOC_OVERRUN_CHECK_OVERHEAD \
+ (2 * XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE)
+
+/* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to
+ hold a size_t value and (2) the header size is a multiple of the
+ alignment that Emacs needs for C types and for USE_LSB_TAG. */
+# define XMALLOC_BASE_ALIGNMENT \
+ offsetof ( \
+ struct { \
+ union { long double d; intmax_t i; void *p; } u; \
+ char c; \
+ }, \
+ c)
+# ifdef USE_LSB_TAG
+/* A common multiple of the positive integers A and B. Ideally this
+ would be the least common multiple, but there's no way to do that
+ as a constant expression in C, so do the best that we can easily do. */
+# define COMMON_MULTIPLE(a, b) \
+ ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b))
+# define XMALLOC_HEADER_ALIGNMENT \
+ COMMON_MULTIPLE (1 << GCTYPEBITS, XMALLOC_BASE_ALIGNMENT)
+# else
+# define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT
+# endif
+# define XMALLOC_OVERRUN_SIZE_SIZE \
+ (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \
+ + XMALLOC_HEADER_ALIGNMENT - 1) \
+ / XMALLOC_HEADER_ALIGNMENT * XMALLOC_HEADER_ALIGNMENT) \
+ - XMALLOC_OVERRUN_CHECK_SIZE)
+#endif
+
extern POINTER_TYPE *xmalloc (size_t);
extern POINTER_TYPE *xrealloc (POINTER_TYPE *, size_t);
extern void xfree (POINTER_TYPE *);