$OpenBSD: patch-src_zmalloc_c,v 1.1 2020/02/11 08:11:13 tb Exp $

zmalloc_size() returns a lie based on the following assumption:

    /* Assume at least that all the allocations are padded at sizeof(long) by
     * the underlying allocator. */

Make that lie a reality by rounding up the actually allocated sizes.

Index: src/zmalloc.c
--- src/zmalloc.c.orig
+++ src/zmalloc.c
@@ -56,6 +56,13 @@ void zlibc_free(void *ptr) {
 #endif
 #endif
 
+static size_t zmalloc_roundsize(size_t size) {
+#ifndef HAVE_MALLOC_SIZE
+     if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));
+#endif
+     return size;
+}
+
 /* Explicitly override malloc/free etc when using tcmalloc. */
 #if defined(USE_TCMALLOC)
 #define malloc(size) tc_malloc(size)
@@ -96,8 +103,11 @@ static void zmalloc_default_oom(size_t size) {
 static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
 
 void *zmalloc(size_t size) {
-    void *ptr = malloc(size+PREFIX_SIZE);
+    void *ptr;
 
+    size = zmalloc_roundsize(size);
+    ptr = malloc(size+PREFIX_SIZE);
+
     if (!ptr) zmalloc_oom_handler(size);
 #ifdef HAVE_MALLOC_SIZE
     update_zmalloc_stat_alloc(zmalloc_size(ptr));
@@ -128,8 +138,11 @@ void zfree_no_tcache(void *ptr) {
 #endif
 
 void *zcalloc(size_t size) {
-    void *ptr = calloc(1, size+PREFIX_SIZE);
+    void *ptr;
 
+    size = zmalloc_roundsize(size);
+    ptr = calloc(1, size+PREFIX_SIZE);
+
     if (!ptr) zmalloc_oom_handler(size);
 #ifdef HAVE_MALLOC_SIZE
     update_zmalloc_stat_alloc(zmalloc_size(ptr));
@@ -147,6 +160,8 @@ void *zrealloc(void *ptr, size_t size) {
 #endif
     size_t oldsize;
     void *newptr;
+
+    size = zmalloc_roundsize(size);
 
     if (ptr == NULL) return zmalloc(size);
 #ifdef HAVE_MALLOC_SIZE
