From 532dff1d641f04e166e37a1d2d6124b69d9d6c72 Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Sat, 2 Jan 2010 21:39:46 +0000 Subject: [PATCH] ITS#6437, fixes for stack implementation of slap_sl_realloc(): Preserve 2*int alignment on hosts where sizeof(int) == sizeof(ber_len_t). If realloc of last block falls back to ch_malloc, free last block properly. Fix range check (ptr + size < endptr) --> (size < endptr - ptr). --- servers/slapd/sl_malloc.c | 55 ++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/servers/slapd/sl_malloc.c b/servers/slapd/sl_malloc.c index a3159b2434..ead25a7317 100644 --- a/servers/slapd/sl_malloc.c +++ b/servers/slapd/sl_malloc.c @@ -337,7 +337,8 @@ void * slap_sl_realloc(void *ptr, ber_len_t size, void *ctx) { struct slab_heap *sh = ctx; - ber_len_t *p = (ber_len_t *)ptr, *newptr; + ber_len_t oldsize, *p = (ber_len_t *) ptr; + void *newptr; if (ptr == NULL) return slap_sl_malloc(size, ctx); @@ -367,6 +368,8 @@ slap_sl_realloc(void *ptr, ber_len_t size, void *ctx) return NULL; } + oldsize = p[-1]; + if (sh->sh_stack) { /* Round up to doubleword boundary, add room for head */ size = ((size + Align-1) & -Align) + sizeof( ber_len_t ); @@ -374,37 +377,41 @@ slap_sl_realloc(void *ptr, ber_len_t size, void *ctx) p--; /* Never shrink blocks */ - if (size <= p[0]) { - newptr = ptr; + if (size <= oldsize) { + return ptr; - /* If reallocing the last block, we can grow it */ - } else if ((char *)ptr + p[0] == sh->sh_last && - (char *)ptr + size < (char *)sh->sh_end ) { - newptr = ptr; - sh->sh_last = (char *)ptr + size; - p[0] = size; - p[size/sizeof(ber_len_t)] = size; + /* If reallocing the last block, try to grow it */ + } else if ((char *) ptr + oldsize == sh->sh_last) { + if (size < (char *) sh->sh_end - (char *) ptr) { + sh->sh_last = (char *) ptr + size; + p[0] = size; + p[size/sizeof(ber_len_t)] = size; + return ptr; + } /* Nowhere to grow, need to alloc and copy */ } else { - newptr = slap_sl_malloc(size-sizeof(ber_len_t), ctx); - AC_MEMCPY(newptr, ptr, p[0]-sizeof(ber_len_t)); - /* mark old region as free */ + /* Slight optimization of the final realloc variant */ + size -= sizeof(ber_len_t); + oldsize -= sizeof(ber_len_t); + newptr = slap_sl_malloc(size, ctx); + AC_MEMCPY(newptr, ptr, oldsize); + /* Not last block, can just mark old region as free */ p[p[0]/sizeof(ber_len_t)] |= 1; + return newptr; } - return newptr; - } else { - void *newptr2; - newptr2 = slap_sl_malloc(size, ctx); - if (size < p[-1]) { - AC_MEMCPY(newptr2, ptr, size); - } else { - AC_MEMCPY(newptr2, ptr, p[-1]); - } - slap_sl_free(ptr, ctx); - return newptr2; + size -= sizeof(ber_len_t); + oldsize -= sizeof(ber_len_t); + + } else if (oldsize > size) { + oldsize = size; } + + newptr = slap_sl_malloc(size, ctx); + AC_MEMCPY(newptr, ptr, oldsize); + slap_sl_free(ptr, ctx); + return newptr; } void -- 2.39.5