diff options
author | Colin Cross <ccross@android.com> | 2016-03-10 13:01:27 -0800 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2016-03-10 14:31:32 -0800 |
commit | 239838608dbe9917acddfe5a51d92350a4c8e135 (patch) | |
tree | 4034bac8a74fc1bc2b7e56b0f360391011bf78b5 | |
parent | 15af478080cfbfa800fb8172fdf70a84075925e3 (diff) | |
download | android_bionic-239838608dbe9917acddfe5a51d92350a4c8e135.tar.gz android_bionic-239838608dbe9917acddfe5a51d92350a4c8e135.tar.bz2 android_bionic-239838608dbe9917acddfe5a51d92350a4c8e135.zip |
malloc_debug: fix multiplication overflow in debug_calloc
The over flow check for nmemb * bytes in debug_calloc is incorrect,
use the builtin overflow functions to check for multiplication and
addition overflow.
Change-Id: I3f1c13102621bc5380be1f69caa88dba2118f3cb
-rw-r--r-- | libc/malloc_debug/malloc_debug.cpp | 12 | ||||
-rw-r--r-- | libc/malloc_debug/tests/malloc_debug_unit_tests.cpp | 6 |
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); |