diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc index 48d4530..37c1440 100644 --- a/src/tcmalloc.cc +++ b/src/tcmalloc.cc @@ -1391,7 +1391,7 @@ ATTRIBUTE_ALWAYS_INLINE inline void* do_calloc(size_t n, size_t elem_size) { void* result = do_malloc_or_cpp_alloc(size); if (result != NULL) { - memset(result, 0, size); + memset(result, 0, tc_nallocx(size, 0)); } return result; } diff --git a/src/windows/override_functions.cc b/src/windows/override_functions.cc index f6f519a..06c4c17 100644 --- a/src/windows/override_functions.cc +++ b/src/windows/override_functions.cc @@ -66,10 +66,25 @@ void* _calloc_base(size_t n, size_t size) { return calloc(n, size); } -void* _recalloc(void* p, size_t n, size_t size) { - void* result = realloc(p, n * size); - memset(result, 0, n * size); - return result; +void* _recalloc(void* old_ptr, size_t n, size_t size) { + // Ensure that (n * size) does not overflow + if (!(n == 0 || (std::numeric_limits::max)() / n >= size)) { + errno = ENOMEM; + return NULL; + } + + const size_t old_size = tc_malloc_size(old_ptr); + const size_t new_size = n * size; + + void* new_ptr = realloc(old_ptr, new_size); + + // If the reallocation succeeded and the new block is larger, zero-fill the + // new bytes: + if (new_ptr != NULL && new_size > old_size) { + memset(static_cast(new_ptr) + old_size, 0, tc_nallocx(new_size, 0) - old_size); + } + + return new_ptr; } void* _calloc_impl(size_t n, size_t size) {