]> granicus.if.org Git - php/commitdiff
Added internal heap protection
authorDmitry Stogov <dmitry@php.net>
Fri, 15 Dec 2006 13:25:47 +0000 (13:25 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 15 Dec 2006 13:25:47 +0000 (13:25 +0000)
  . safe unlinking
  . cookies
  . canary protection (debug build only)

Zend/zend_alloc.c

index 090c12aca94336a29f403597c89abf00e6d5ad2a..ea8580330432d4e7eb22e8aea49a352359be6256 100644 (file)
 # define ZEND_USE_MALLOC_MM ZEND_DEBUG
 #endif
 
+#ifndef ZEND_MM_HEAP_PROTECTION
+# define ZEND_MM_HEAP_PROTECTION ZEND_DEBUG
+#endif
+
+#ifndef ZEND_MM_SAFE_UNLINKING
+# define ZEND_MM_SAFE_UNLINKING 1
+#endif
+
+#ifndef ZEND_MM_COOKIES
+# define ZEND_MM_COOKIES 1
+#endif
+
 #if ZEND_DEBUG
 void zend_debug_alloc_output(char *format, ...)
 {
@@ -54,6 +66,15 @@ void zend_debug_alloc_output(char *format, ...)
 }
 #endif
 
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
+# define EXPECTED(condition)   __builtin_expect(condition, 1)
+# define UNEXPECTED(condition) __builtin_expect(condition, 0)
+static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
+#else
+# define EXPECTED(condition)   (condition)
+# define UNEXPECTED(condition) (condition)
+#endif
+
 static void zend_mm_panic(const char *message)
 {
        fprintf(stderr, "%s\n", message);
@@ -189,7 +210,7 @@ static zend_mm_storage* zend_mm_mem_win32_init(void *params)
 {
        HANDLE heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
        zend_mm_storage* storage;
-       
+
        if (heap == NULL) {
                return NULL;
        }
@@ -281,24 +302,43 @@ typedef enum _mem_magic {
 typedef struct _zend_mm_block_info {
        size_t _size;
        size_t _prev;
+#if ZEND_MM_COOKIES
+       unsigned long _cookie;
+#endif
 } zend_mm_block_info;
 
+#if ZEND_DEBUG
+
 typedef struct _zend_mm_debug_info {
        char *filename;
        uint lineno;
        char *orig_filename;
        uint orig_lineno;
        size_t size;
+#if ZEND_MM_HEAP_PROTECTION
+       unsigned int start_magic;
+#endif
 } zend_mm_debug_info;
 
+#elif ZEND_MM_HEAP_PROTECTION
+
+typedef struct _zend_mm_debug_info {
+       size_t size;
+       unsigned int start_magic;
+} zend_mm_debug_info;
+
+#endif
+
 typedef struct _zend_mm_block {
        zend_mm_block_info info;
 #if ZEND_DEBUG
        mem_magic magic;
-       zend_mm_debug_info debug;
 # ifdef ZTS
        THREAD_T thread_id;
 # endif
+       zend_mm_debug_info debug;
+#elif ZEND_MM_HEAP_PROTECTION
+       zend_mm_debug_info debug;
 #endif
 } zend_mm_block;
 
@@ -306,6 +346,9 @@ typedef struct _zend_mm_free_block {
        zend_mm_block_info info;
 #if ZEND_DEBUG
        mem_magic magic;
+# ifdef ZTS
+       THREAD_T thread_id;
+# endif
 #endif
        struct _zend_mm_free_block *prev_free_block;
        struct _zend_mm_free_block *next_free_block;
@@ -340,6 +383,24 @@ struct _zend_mm_heap {
        zend_mm_free_block  free_buckets[ZEND_MM_NUM_BUCKETS];
 };
 
+
+#if ZEND_MM_COOKIES
+
+static unsigned int _zend_mm_cookie = 0;
+
+# define ZEND_MM_COOKIE(block) \
+       (((unsigned long)(block)) ^ _zend_mm_cookie)
+# define ZEND_MM_SET_COOKIE(block) \
+       (block)->info._cookie = ZEND_MM_COOKIE(block)
+# define ZEND_MM_CHECK_COOKIE(block) \
+       if (UNEXPECTED((block)->info._cookie != ZEND_MM_COOKIE(block))) { \
+               zend_mm_panic("zend_mm_heap corrupted"); \
+       }
+#else
+# define ZEND_MM_SET_COOKIE(block)
+# define ZEND_MM_CHECK_COOKIE(block)
+#endif
+
 /* Reserved space for error reporting in case of memory overflow */
 #define ZEND_MM_RESERVE_SIZE            8*1024
 
@@ -353,6 +414,7 @@ struct _zend_mm_heap {
                                                                                        size_t _size = (size); \
                                                                                        (b)->info._size = (type) | _size; \
                                                                                        ZEND_MM_BLOCK_AT(b, _size)->info._prev = (type) | _size; \
+                                                                                       ZEND_MM_SET_COOKIE(b); \
                                                                                } while (0);
 #define ZEND_MM_LAST_BLOCK(b)                  do { \
                (b)->info._size = ZEND_MM_GUARD_BLOCK | ZEND_MM_ALIGNED_HEADER_SIZE; \
@@ -413,8 +475,11 @@ struct _zend_mm_heap {
 #if ZEND_DEBUG
 
 # ifdef ZTS
+#  define ZEND_MM_SET_THREAD_ID(block) \
+       ((zend_mm_block*)(block))->thread_id = tsrm_thread_id()
 #  define ZEND_MM_BAD_THREAD_ID(block) ((block)->thread_id != tsrm_thread_id())
 # else
+#  define ZEND_MM_SET_THREAD_ID(block)
 #  define ZEND_MM_BAD_THREAD_ID(block) 0
 # endif
 
@@ -427,38 +492,91 @@ struct _zend_mm_heap {
 
 # define ZEND_MM_CHECK_MAGIC(block, val) do { \
                if ((block)->magic != (val)) { \
-                       zend_mm_panic("Heap corrupted"); \
+                       zend_mm_panic("zend_mm_heap corrupted"); \
                } \
        } while (0)
 
-# define ZEND_MM_END_MAGIC_PTR(block) \
-       (long*)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->debug.size)
-
-# define ZEND_MM_SET_END_MAGIC(block) do { \
-               long *p = ZEND_MM_END_MAGIC_PTR(block); \
-               memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \
+# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) do { \
+               ((zend_mm_block*)(block))->debug.filename = __zend_filename; \
+               ((zend_mm_block*)(block))->debug.lineno = __zend_lineno; \
+               ((zend_mm_block*)(block))->debug.orig_filename = __zend_orig_filename; \
+               ((zend_mm_block*)(block))->debug.orig_lineno = __zend_orig_lineno; \
+               ZEND_MM_SET_BLOCK_SIZE(block, __size); \
+               if (set_valid) { \
+                       ZEND_MM_SET_MAGIC(block, MEM_BLOCK_VALID); \
+               } \
+               if (set_thread) { \
+                       ZEND_MM_SET_THREAD_ID(block); \
+               } \
        } while (0)
 
-# define MEM_BLOCK_END_MAGIC 0x2A8FCC84L
-
-# define END_MAGIC_SIZE sizeof(long)
-
-static long _mem_block_end_magic = MEM_BLOCK_END_MAGIC;
-
 #else
 
 # define ZEND_MM_VALID_PTR(ptr) (ptr != NULL)
 
 # define ZEND_MM_SET_MAGIC(block, val)
 
-# define ZEND_MM_SET_END_MAGIC(block)
-
 # define ZEND_MM_CHECK_MAGIC(block, val)
 
+# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) ZEND_MM_SET_BLOCK_SIZE(block, __size)
+
+#endif
+
+
+#if ZEND_MM_HEAP_PROTECTION
+
+# define ZEND_MM_CHECK_PROTECTION(block) \
+       do { \
+               if ((block)->debug.start_magic != _mem_block_start_magic || \
+                   memcmp(ZEND_MM_END_MAGIC_PTR(block), &_mem_block_end_magic, END_MAGIC_SIZE) != 0) { \
+                   zend_mm_panic("zend_mm_heap corrupted"); \
+               } \
+       } while (0)
+
+# define ZEND_MM_END_MAGIC_PTR(block) \
+       (unsigned int*)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->debug.size)
+
+# define END_MAGIC_SIZE sizeof(unsigned int)
+
+# define ZEND_MM_SET_BLOCK_SIZE(block, __size) do { \
+               unsigned int *p; \
+               ((zend_mm_block*)(block))->debug.size = (__size); \
+               p = ZEND_MM_END_MAGIC_PTR(block); \
+               ((zend_mm_block*)(block))->debug.start_magic = _mem_block_start_magic; \
+               memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \
+       } while (0)
+
+static unsigned int _mem_block_start_magic = 0;
+static unsigned int _mem_block_end_magic   = 0;
+
+#else
+
+# if ZEND_DEBUG
+#  define ZEND_MM_SET_BLOCK_SIZE(block, _size) \
+       ((zend_mm_block*)(block))->debug.size = (_size)
+# else
+#  define ZEND_MM_SET_BLOCK_SIZE(block, _size)
+# endif
+
+# define ZEND_MM_CHECK_PROTECTION(block)
+
 # define END_MAGIC_SIZE 0
 
 #endif
 
+#if ZEND_MM_SAFE_UNLINKING
+# define ZEND_MM_CHECK_BLOCK_LINKAGE(block) \
+       if (UNEXPECTED((block)->info._size != ZEND_MM_NEXT_BLOCK(block)->info._prev) || \
+               UNEXPECTED(!UNEXPECTED(ZEND_MM_IS_FIRST_BLOCK(block)) && \
+           UNEXPECTED(ZEND_MM_PREV_BLOCK(block)->info._size != (block)->info._prev))) { \
+           zend_mm_panic("zend_mm_heap corrupted"); \
+       }
+#else
+# define ZEND_MM_CHECK_BLOCK_LINKAGE(block)
+#endif
+
+
+
 static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
 {
        zend_mm_free_block *prev, *next;
@@ -497,6 +615,13 @@ static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_fre
 
        prev = mm_block->prev_free_block;
        next = mm_block->next_free_block;
+
+#if ZEND_MM_SAFE_UNLINKING
+       if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) {
+               zend_mm_panic("zend_mm_heap corrupted");
+       }
+#endif
+
        prev->next_free_block = next;
        next->prev_free_block = prev;
 
@@ -612,6 +737,41 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers,
        exit(0);
 #endif
 
+#if ZEND_MM_HEAP_PROTECTION
+       if (_mem_block_start_magic == 0) {
+               int r;
+               do {
+                       r = rand();
+               } while (!(r&0xff000000) ||
+                        !(r&0x00ff0000) ||
+                        !(r&0x0000ff00) ||
+                        !(r&0x000000ff));
+               _mem_block_start_magic = r;
+       }
+       if (_mem_block_end_magic == 0) {
+               int r;
+               do {
+                       r = rand();
+               } while (!(r&0xff000000) ||
+                        !(r&0x00ff0000) ||
+                        !(r&0x0000ff00) ||
+                        !(r&0x000000ff));
+               _mem_block_end_magic = r;
+       }
+#endif
+#if ZEND_MM_COOKIES
+       if (_zend_mm_cookie == 0) {
+               int r;
+               do {
+                       r = rand();
+               } while (!(r&0xff000000) ||
+                        !(r&0x00ff0000) ||
+                        !(r&0x0000ff00) ||
+                        !(r&0x000000ff));
+               _zend_mm_cookie = r;
+       }
+#endif
+
        storage = handlers->init(params);
        if (!storage) {
                fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name);
@@ -790,7 +950,6 @@ static int zend_mm_check_ptr(zend_mm_heap *heap, void *ptr, int silent ZEND_FILE
        int no_cache_notice = 0;
        int had_problems = 0;
        int valid_beginning = 1;
-       long *end_magic;
 
        if (silent==2) {
                silent = 1;
@@ -926,43 +1085,80 @@ static int zend_mm_check_ptr(zend_mm_heap *heap, void *ptr, int silent ZEND_FILE
                }
        }
 
-       end_magic = ZEND_MM_END_MAGIC_PTR(p);
+#if ZEND_MM_HEAP_PROTECTION
        if (!valid_beginning) {
                if (!silent) {
-                       zend_debug_alloc_output("%10s\t", "End:");
+                       zend_debug_alloc_output("%10s\t", "Start:");
                        zend_debug_alloc_output("Unknown\n");
-               }
-       } else if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
-               if (!silent) {
                        zend_debug_alloc_output("%10s\t", "End:");
-                       zend_debug_alloc_output("OK\n");
+                       zend_debug_alloc_output("Unknown\n");
                }
        } else {
-               char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
-               int overflows=0;
-               long i;
+               unsigned int *end_magic = ZEND_MM_END_MAGIC_PTR(p);
 
-               if (silent) {
-                       return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
-               }
-               had_problems = 1;
-               overflow_ptr = (char *) end_magic;
+               if (p->debug.start_magic == _mem_block_start_magic) {
+                       if (!silent) {
+                               zend_debug_alloc_output("%10s\t", "Start:");
+                               zend_debug_alloc_output("OK\n");
+                       }
+               } else {
+                       char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic;
+                       int overflows=0;
+                       int i;
 
-               for (i=0; i<(int)sizeof(long); i++) {
-                       if (overflow_ptr[i]!=magic_ptr[i]) {
-                               overflows++;
+                       if (silent) {
+                               return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+                       }
+                       had_problems = 1;
+                       overflow_ptr = (char *) &p->debug.start_magic;
+                       i = END_MAGIC_SIZE;
+                       while (--i >= 0) {
+                               if (overflow_ptr[i]!=magic_ptr[i]) {
+                                       overflows++;
+                               }
+                       }
+                       zend_debug_alloc_output("%10s\t", "Start:");
+                       zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic);
+                       zend_debug_alloc_output("%10s\t","");
+                       if (overflows >= END_MAGIC_SIZE) {
+                               zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
+                       } else {
+                               zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
                        }
                }
-
-               zend_debug_alloc_output("%10s\t", "End:");
-               zend_debug_alloc_output("Overflown (magic=0x%0.8lX instead of 0x%0.8lX)\n", *end_magic, MEM_BLOCK_END_MAGIC);
-               zend_debug_alloc_output("%10s\t","");
-               if (overflows>=(int)sizeof(long)) {
-                       zend_debug_alloc_output("At least %d bytes overflown\n", sizeof(long));
+               if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
+                       if (!silent) {
+                               zend_debug_alloc_output("%10s\t", "End:");
+                               zend_debug_alloc_output("OK\n");
+                       }
                } else {
-                       zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
+                       char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
+                       int overflows=0;
+                       int i;
+
+                       if (silent) {
+                               return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+                       }
+                       had_problems = 1;
+                       overflow_ptr = (char *) end_magic;
+
+                       for (i=0; i < END_MAGIC_SIZE; i++) {
+                               if (overflow_ptr[i]!=magic_ptr[i]) {
+                                       overflows++;
+                               }
+                       }
+
+                       zend_debug_alloc_output("%10s\t", "End:");
+                       zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic);
+                       zend_debug_alloc_output("%10s\t","");
+                       if (overflows >= END_MAGIC_SIZE) {
+                               zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
+                       } else {
+                               zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
+                       }
                }
        }
+#endif
 
        if (!silent) {
                zend_debug_alloc_output("---------------------------------------\n");
@@ -1132,16 +1328,8 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
                        best_fit = heap->cache[index];
                        heap->cache[index] = best_fit->prev_free_block;
                        heap->cached -= true_size;
-#if ZEND_DEBUG
                        ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
-                       ZEND_MM_SET_MAGIC(best_fit, MEM_BLOCK_VALID);
-                       ((zend_mm_block*)best_fit)->debug.size = size;
-                       ((zend_mm_block*)best_fit)->debug.filename = __zend_filename;
-                       ((zend_mm_block*)best_fit)->debug.lineno = __zend_lineno;
-                       ((zend_mm_block*)best_fit)->debug.orig_filename = __zend_orig_filename;
-                       ((zend_mm_block*)best_fit)->debug.orig_lineno = __zend_orig_lineno;
-                       ZEND_MM_SET_END_MAGIC(best_fit);
-#endif
+                       ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
                        return ZEND_MM_DATA_OF(best_fit);
                }
 #endif
@@ -1191,6 +1379,8 @@ zend_mm_finished_searching_for_block:
 #if ZEND_DEBUG
                ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
 #endif
+               ZEND_MM_CHECK_COOKIE(best_fit);
+               ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
                zend_mm_remove_from_free_list(heap, best_fit);
 
                {
@@ -1295,18 +1485,7 @@ zend_mm_finished_searching_for_block:
                }
        }
 
-#if ZEND_DEBUG
-       ZEND_MM_SET_MAGIC(best_fit, MEM_BLOCK_VALID);
-       ((zend_mm_block*)best_fit)->debug.size = size;
-       ((zend_mm_block*)best_fit)->debug.filename = __zend_filename;
-       ((zend_mm_block*)best_fit)->debug.lineno = __zend_lineno;
-       ((zend_mm_block*)best_fit)->debug.orig_filename = __zend_orig_filename;
-       ((zend_mm_block*)best_fit)->debug.orig_lineno = __zend_orig_lineno;
-# ifdef ZTS
-       ((zend_mm_block*)best_fit)->thread_id = tsrm_thread_id();
-# endif
-       ZEND_MM_SET_END_MAGIC(best_fit);
-#endif
+       ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
 
 #if MEMORY_LIMIT
        heap->size += true_size;
@@ -1332,8 +1511,9 @@ static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND
        }
        mm_block = ZEND_MM_HEADER_OF(p);
        size = ZEND_MM_BLOCK_SIZE(mm_block);
+       ZEND_MM_CHECK_PROTECTION(mm_block);
 
-#if ZEND_DEBUG
+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
        memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
 #endif
 
@@ -1429,7 +1609,8 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
        mm_block = ZEND_MM_HEADER_OF(p);
        true_size = ZEND_MM_TRUE_SIZE(size);
        orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
-       
+       ZEND_MM_CHECK_PROTECTION(mm_block);
+
        if (true_size <= orig_size) {
                size_t remaining_size = orig_size - true_size;
 
@@ -1456,20 +1637,15 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
 #endif
                        HANDLE_UNBLOCK_INTERRUPTIONS();
                }
-#if ZEND_DEBUG
-               mm_block->debug.size = size;
-               mm_block->debug.filename = __zend_filename;
-               mm_block->debug.lineno = __zend_lineno;
-               mm_block->debug.orig_filename = __zend_orig_filename;
-               mm_block->debug.orig_lineno = __zend_orig_lineno;
-               ZEND_MM_SET_END_MAGIC(mm_block);
-#endif
+               ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
                return p;
        }
 
        next_block = ZEND_MM_NEXT_BLOCK(mm_block);
 
        if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
+               ZEND_MM_CHECK_COOKIE(next_block);
+               ZEND_MM_CHECK_BLOCK_LINKAGE(next_block);
                if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) {
                        size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
                        size_t remaining_size = block_size - true_size;
@@ -1491,14 +1667,7 @@ static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_
                                /* add the new free block to the free list */
                                zend_mm_add_to_free_list(heap, new_free_block);
                        }
-#if ZEND_DEBUG
-                       mm_block->debug.size = size;
-                       mm_block->debug.filename = __zend_filename;
-                       mm_block->debug.lineno = __zend_lineno;
-                       mm_block->debug.orig_filename = __zend_orig_filename;
-                       mm_block->debug.orig_lineno = __zend_orig_lineno;
-                       ZEND_MM_SET_END_MAGIC(mm_block);
-#endif
+                       ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
 #if MEMORY_LIMIT
                        heap->size = heap->size + true_size - orig_size;
                        if (heap->peak < heap->size) {
@@ -1605,18 +1774,7 @@ realloc_segment:
                        zend_mm_add_to_free_list(heap, new_free_block);
                }
 
-#if ZEND_DEBUG
-               ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_VALID);
-               mm_block->debug.size = size;
-               mm_block->debug.filename = __zend_filename;
-               mm_block->debug.lineno = __zend_lineno;
-               mm_block->debug.orig_filename = __zend_orig_filename;
-               mm_block->debug.orig_lineno = __zend_orig_lineno;
-# ifdef ZTS
-               mm_block->thread_id = tsrm_thread_id();
-# endif
-               ZEND_MM_SET_END_MAGIC(mm_block);
-#endif
+               ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1);
 #if MEMORY_LIMIT
                heap->size = heap->size + true_size - orig_size;
                if (heap->peak < heap->size) {
@@ -1628,7 +1786,7 @@ realloc_segment:
        }
 
        ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
-#if ZEND_DEBUG
+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
        memcpy(ptr, p, mm_block->debug.size);
 #else
        memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
@@ -1660,7 +1818,8 @@ ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_D
                return 0;
        }
        mm_block = ZEND_MM_HEADER_OF(p);
-#if ZEND_DEBUG
+       ZEND_MM_CHECK_PROTECTION(mm_block);
+#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
        return mm_block->debug.size;
 #else
        return ZEND_MM_BLOCK_SIZE(mm_block);