aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libc/malloc_debug/malloc_debug.cpp12
-rw-r--r--libc/malloc_debug/tests/malloc_debug_unit_tests.cpp6
2 files changed, 15 insertions, 3 deletions
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index b20d634b2..568192d69 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -538,13 +538,19 @@ void* debug_calloc(size_t nmemb, size_t bytes) {
return g_dispatch->calloc(nmemb, bytes);
}
- size_t size = nmemb * bytes;
+ size_t size;
+ if (__builtin_mul_overflow(nmemb, bytes, &size)) {
+ // Overflow
+ errno = ENOMEM;
+ return nullptr;
+ }
+
if (size == 0) {
size = 1;
}
- size_t real_size = size + g_debug->extra_bytes();
- if (real_size < bytes || real_size < nmemb) {
+ size_t real_size;
+ if (__builtin_add_overflow(size, g_debug->extra_bytes(), &real_size)) {
// Overflow.
errno = ENOMEM;
return nullptr;
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 28729e8ac..2503981b0 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -1290,6 +1290,12 @@ TEST_F(MallocDebugTest, overflow) {
ASSERT_TRUE(pointer == nullptr);
ASSERT_EQ(ENOMEM, errno);
+ const size_t size_t_bits = sizeof(size_t) * 8;
+ const size_t sqrt_size_t = 1ULL << (size_t_bits/2);
+ pointer = debug_calloc(sqrt_size_t + 1, sqrt_size_t);
+ ASSERT_TRUE(pointer == nullptr);
+ ASSERT_EQ(ENOMEM, errno);
+
pointer = debug_realloc(nullptr, SIZE_MAX);
ASSERT_TRUE(pointer == nullptr);
ASSERT_EQ(ENOMEM, errno);