mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-28 08:11:05 -08:00
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.
This commit is contained in:
parent
5f91c1e530
commit
cb993c584c
4 changed files with 84 additions and 33 deletions
|
|
@ -1,3 +1,23 @@
|
|||
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,
|
||||
|
|
|
|||
47
src/alloc.c
47
src/alloc.c
|
|
@ -482,27 +482,10 @@ buffer_memory_full (EMACS_INT nbytes)
|
|||
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',
|
||||
|
|
@ -522,9 +505,9 @@ static void
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -534,8 +517,8 @@ xmalloc_get_size (unsigned char *ptr)
|
|||
{
|
||||
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++;
|
||||
|
|
@ -579,7 +562,7 @@ overrun_check_malloc (size_t size)
|
|||
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);
|
||||
|
|
@ -603,7 +586,7 @@ overrun_check_realloc (POINTER_TYPE *block, size_t 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);
|
||||
|
|
@ -611,8 +594,8 @@ overrun_check_realloc (POINTER_TYPE *block, size_t size)
|
|||
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);
|
||||
|
|
@ -620,7 +603,7 @@ overrun_check_realloc (POINTER_TYPE *block, size_t size)
|
|||
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);
|
||||
|
|
@ -640,7 +623,7 @@ overrun_check_free (POINTER_TYPE *block)
|
|||
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);
|
||||
|
|
@ -648,12 +631,12 @@ overrun_check_free (POINTER_TYPE *block)
|
|||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2337,7 +2337,7 @@ syms_of_charset (void)
|
|||
mmap for larger allocations, and these don't work well across dumped
|
||||
systems. */
|
||||
enum {
|
||||
initial_malloc_max = (1 << 16) - 1,
|
||||
initial_malloc_max = (1 << 16) - 1 - XMALLOC_OVERRUN_CHECK_OVERHEAD,
|
||||
charset_table_size_init = initial_malloc_max / sizeof (struct charset)
|
||||
};
|
||||
|
||||
|
|
|
|||
48
src/lisp.h
48
src/lisp.h
|
|
@ -3568,6 +3568,54 @@ extern int initialized;
|
|||
|
||||
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 *);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue