From 532dff1d641f04e166e37a1d2d6124b69d9d6c72 Mon Sep 17 00:00:00 2001
From: Hallvard Furuseth <hallvard@openldap.org>
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
-- 
GitLab