From aea07e2c6e54733804d0be54e97d44fcb3df63dd Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 6 Nov 2013 21:31:04 -0800 Subject: [PATCH] Port to C11 aligned_alloc, and fix some integer overflows. * configure.ac (GMALLOC_OBJ): Initialize to empty if !system_malloc and doug_lea_malloc. (aligned_alloc): Test for existence if !GMALLOC_OBJ and not darwin. (posix_memalign): Test for existence only if !GMALLOC_OBJ and not darwin and !aligned_alloc. * src/alloc.c (USE_ALIGNED_ALLOC): New symbol. (USE_POSIX_MEMALIGN): Remove. All uses replaced with USE_ALIGNED_ALLOC, and use of posix_memalign replaced with aligned_alloc. (aligned_alloc): New function, defined or declared as needed. * src/conf_post.h (HAVE_POSIX_MEMALIGN) [DARWIN_OS]: Don't undef; configure.ac now does this. * src/gmalloc.c (aligned_alloc) [MSDOS]: New decl. (calloc, aligned_alloc): Check for integer overflow. (aligned_alloc): Rename from memalign. All uses changed. (memalign): New function, an alias for aligned_alloc. --- ChangeLog | 9 +++++++++ configure.ac | 18 ++++++++++++++---- src/ChangeLog | 14 ++++++++++++++ src/alloc.c | 31 +++++++++++++++++++------------ src/conf_post.h | 2 -- src/gmalloc.c | 42 ++++++++++++++++++++++++++++++++---------- 6 files changed, 88 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ae941aa4e..05ab15e0da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2013-11-07 Paul Eggert + + Port to C11 aligned_alloc. + * configure.ac (GMALLOC_OBJ): Initialize to empty if !system_malloc + and doug_lea_malloc. + (aligned_alloc): Test for existence if !GMALLOC_OBJ and not darwin. + (posix_memalign): Test for existence only if !GMALLOC_OBJ and + not darwin and !aligned_alloc. + 2013-11-05 Glenn Morris * configure.ac (abs_srcdir) [MINGW32]: No point setting it here, diff --git a/configure.ac b/configure.ac index a8fb34b709..bd8278d3b7 100644 --- a/configure.ac +++ b/configure.ac @@ -1895,12 +1895,14 @@ case "$opsys" in darwin|sol2-10) system_malloc=yes ;; esac +GMALLOC_OBJ= if test "${system_malloc}" = "yes"; then - AC_DEFINE(SYSTEM_MALLOC, 1, [Define to use system malloc.]) + AC_DEFINE([SYSTEM_MALLOC], 1, + [Define to 1 to use the system memory allocator, even if it is not + Doug Lea style.]) GNU_MALLOC=no GNU_MALLOC_reason=" (The GNU allocators don't work with this system configuration.)" - GMALLOC_OBJ= VMLIMIT_OBJ= else test "$doug_lea_malloc" != "yes" && GMALLOC_OBJ=gmalloc.o @@ -1929,7 +1931,8 @@ if test "$doug_lea_malloc" = "yes" ; then (Using Doug Lea's new malloc from the GNU C Library.)" fi AC_DEFINE(DOUG_LEA_MALLOC, 1, - [Define to 1 if you are using the GNU C Library.]) + [Define to 1 if the system memory allocator is Doug Lea style, + with malloc hooks and malloc_set_state.]) ## Use mmap directly for allocating larger buffers. ## FIXME this comes from src/s/{gnu,gnu-linux}.h: @@ -3372,11 +3375,18 @@ getrlimit setrlimit shutdown getaddrinfo \ strsignal setitimer \ sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \ gai_strerror getline getdelim sync \ -difftime posix_memalign \ +difftime \ getpwent endpwent getgrent endgrent \ touchlock \ cfmakeraw cfsetspeed copysign __executable_start log2) +dnl No need to check for aligned_alloc and posix_memalign if using +dnl gmalloc.o, as it supplies them. Don't use these functions on +dnl Darwin as they are incompatible with unexmacosx.c. +if test -z "$GMALLOC_OBJ" && test "$opsys" != darwin; then + AC_CHECK_FUNCS([aligned_alloc posix_memalign], [break]) +fi + ## Eric Backus says, HP-UX 9.x on HP 700 machines ## has a broken `rint' in some library versions including math library ## version number A.09.05. diff --git a/src/ChangeLog b/src/ChangeLog index d008f67086..2f774b87b1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2013-11-07 Paul Eggert + + Port to C11 aligned_alloc, and fix some integer overflows. + * alloc.c (USE_ALIGNED_ALLOC): New symbol. + (USE_POSIX_MEMALIGN): Remove. All uses replaced with USE_ALIGNED_ALLOC, + and use of posix_memalign replaced with aligned_alloc. + (aligned_alloc): New function, defined or declared as needed. + * conf_post.h (HAVE_POSIX_MEMALIGN) [DARWIN_OS]: + Don't undef; configure.ac now does this. + * gmalloc.c (aligned_alloc) [MSDOS]: New decl. + (calloc, aligned_alloc): Check for integer overflow. + (aligned_alloc): Rename from memalign. All uses changed. + (memalign): New function, an alias for aligned_alloc. + 2013-11-06 Stefan Monnier * xdisp.c (redisplay_internal): Fix typo in last change. diff --git a/src/alloc.c b/src/alloc.c index 7054083acb..bc5ed6d94b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -920,8 +920,20 @@ lisp_free (void *block) /* The entry point is lisp_align_malloc which returns blocks of at most BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ -#if defined (HAVE_POSIX_MEMALIGN) && defined (SYSTEM_MALLOC) -#define USE_POSIX_MEMALIGN 1 +#if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC +# define USE_ALIGNED_ALLOC 1 +/* Defined in gmalloc.c. */ +void *aligned_alloc (size_t, size_t); +#elif defined HAVE_ALIGNED_ALLOC +# define USE_ALIGNED_ALLOC 1 +#elif defined HAVE_POSIX_MEMALIGN +# define USE_ALIGNED_ALLOC 1 +static void * +aligned_alloc (size_t alignment, size_t size) +{ + void *p; + return posix_memalign (&p, alignment, size) == 0 ? p : 0; +} #endif /* BLOCK_ALIGN has to be a power of 2. */ @@ -931,7 +943,7 @@ lisp_free (void *block) malloc a chance to minimize the amount of memory wasted to alignment. It should be tuned to the particular malloc library used. On glibc-2.3.2, malloc never tries to align, so a padding of 0 is best. - posix_memalign on the other hand would ideally prefer a value of 4 + aligned_alloc on the other hand would ideally prefer a value of 4 because otherwise, there's 1020 bytes wasted between each ablocks. In Emacs, testing shows that those 1020 can most of the time be efficiently used by malloc to place other objects, so a value of 0 can @@ -976,7 +988,7 @@ struct ablocks struct ablock blocks[ABLOCKS_SIZE]; }; -/* Size of the block requested from malloc or posix_memalign. */ +/* Size of the block requested from malloc or aligned_alloc. */ #define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING) #define ABLOCK_ABASE(block) \ @@ -988,7 +1000,7 @@ struct ablocks #define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase) /* Pointer to the (not necessarily aligned) malloc block. */ -#ifdef USE_POSIX_MEMALIGN +#ifdef USE_ALIGNED_ALLOC #define ABLOCKS_BASE(abase) (abase) #else #define ABLOCKS_BASE(abase) \ @@ -1027,13 +1039,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) mallopt (M_MMAP_MAX, 0); #endif -#ifdef USE_POSIX_MEMALIGN - { - int err = posix_memalign (&base, BLOCK_ALIGN, ABLOCKS_BYTES); - if (err) - base = NULL; - abase = base; - } +#ifdef USE_ALIGNED_ALLOC + abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES); #else base = malloc (ABLOCKS_BYTES); abase = ALIGN (base, BLOCK_ALIGN); diff --git a/src/conf_post.h b/src/conf_post.h index 786105864f..2d967c0fef 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -49,8 +49,6 @@ along with GNU Emacs. If not, see . */ #define malloc unexec_malloc #define realloc unexec_realloc #define free unexec_free -/* Don't use posix_memalign because it is not compatible with unexmacosx.c. */ -#undef HAVE_POSIX_MEMALIGN #endif /* The following solves the problem that Emacs hangs when evaluating (make-comint "test0" "/nodir/nofile" nil "") when /nodir/nofile diff --git a/src/gmalloc.c b/src/gmalloc.c index bc1d85ac5f..fc728eeea7 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -58,6 +58,7 @@ extern void free (void *ptr); /* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ #ifdef MSDOS +extern void *aligned_alloc (size_t, size_t); extern void *memalign (size_t, size_t); extern int posix_memalign (void **, size_t, size_t); #endif @@ -143,11 +144,11 @@ struct list /* Free list headers for each fragment size. */ extern struct list _fraghead[]; -/* List of blocks allocated with `memalign' (or `valloc'). */ +/* List of blocks allocated with aligned_alloc and friends. */ struct alignlist { struct alignlist *next; - void *aligned; /* The address that memaligned returned. */ + void *aligned; /* The address that aligned_alloc returned. */ void *exact; /* The address that malloc returned. */ }; extern struct alignlist *_aligned_blocks; @@ -977,7 +978,7 @@ License along with this library. If not, see . /* Debugging hook for free. */ void (*__free_hook) (void *__ptr); -/* List of blocks allocated by memalign. */ +/* List of blocks allocated by aligned_alloc. */ struct alignlist *_aligned_blocks = NULL; /* Return memory to the heap. @@ -1487,13 +1488,20 @@ License along with this library. If not, see . /* Allocate an array of NMEMB elements each SIZE bytes long. The entire array is initialized to zeros. */ void * -calloc (register size_t nmemb, register size_t size) +calloc (size_t nmemb, size_t size) { - register void *result = malloc (nmemb * size); + void *result; + size_t bytes = nmemb * size; - if (result != NULL) - (void) memset (result, 0, nmemb * size); + if (size != 0 && bytes / size != nmemb) + { + errno = ENOMEM; + return NULL; + } + result = malloc (bytes); + if (result) + memset (result, 0, bytes); return result; } /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. @@ -1559,7 +1567,7 @@ License along with this library. If not, see . * void *(*__memalign_hook) (size_t size, size_t alignment); void * -memalign (size_t alignment, size_t size) +aligned_alloc (size_t alignment, size_t size) { void *result; size_t adj, lastadj; @@ -1570,6 +1578,11 @@ memalign (size_t alignment, size_t size) /* Allocate a block with enough extra space to pad the block with up to (ALIGNMENT - 1) bytes if necessary. */ + if (- size < alignment) + { + errno = ENOMEM; + return NULL; + } result = malloc (size + alignment - 1); if (result == NULL) return NULL; @@ -1631,6 +1644,15 @@ memalign (size_t alignment, size_t size) return result; } +/* An obsolete alias for aligned_alloc, for any old libraries that use + this alias. */ + +void * +memalign (size_t alignment, size_t size) +{ + return aligned_alloc (alignment, size); +} + int posix_memalign (void **memptr, size_t alignment, size_t size) { @@ -1641,7 +1663,7 @@ posix_memalign (void **memptr, size_t alignment, size_t size) || (alignment & (alignment - 1)) != 0) return EINVAL; - mem = memalign (alignment, size); + mem = aligned_alloc (alignment, size); if (mem == NULL) return ENOMEM; @@ -1686,7 +1708,7 @@ valloc (size_t size) if (pagesize == 0) pagesize = getpagesize (); - return memalign (pagesize, size); + return aligned_alloc (pagesize, size); } #ifdef GC_MCHECK -- 2.20.1