TEST_F(MallocTests, LeakCheck) { char* low = (char *) custom_malloc(1); char* high = low; custom_free(low); char* p, *q, *r; for(int i = 0; i < 10000; i++){ p = (char *) custom_malloc(4096); q = (char *) custom_malloc(4096 * 2 + 1); r = (char *) custom_malloc(1); if (p < low) low = p; if (q < low) low = q; if (r < low) low = r; if (p > high) high = p; if (q > high) high = q; if (r > high) high = r; custom_free(p); custom_free(q); custom_free(r); } ASSERT_TRUE((uint64_t) high - (uint64_t) low < 4096 * 2); }
int main(void) { int *array, *array3; int x; array = custom_alloc(sizeof(int) * 10); array[8] = 8; array[9] = 8; array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock) custom_free(array); // ok custom_free((void*)0x1); // invalid free array3 = malloc(sizeof(int) * 10); custom_free(array3); // mismatched free (ok without MALLOCLIKE) make_leak(); x = array[0]; // use after free (ok without MALLOCLIKE/MAKE_MEM_NOACCESS) // (nb: initialised because is_zeroed==1 above) // unfortunately not identified as being in a free'd // block because the freeing of the block and shadow // chunk isn't postponed. // Bug 137073: passing 0 to MALLOCLIKE_BLOCK was causing an assertion // failure. Test for this (and likewise for FREELIKE_BLOCK). VALGRIND_MALLOCLIKE_BLOCK(0,0,0,0); VALGRIND_FREELIKE_BLOCK(0,0); return x; // leak from make_leak() }
int main(void) { int* array; int* array3; array = custom_alloc(sizeof(int) * 10); array[8] = 8; array[9] = 8; array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock) custom_free(array); // ok custom_free(NULL); // invalid free (ok without MALLOCLIKE) array3 = malloc(sizeof(int) * 10); custom_free(array3); // mismatched free (ok without MALLOCLIKE) make_leak(); return array[0]; // use after free (ok without MALLOCLIKE) // (nb: initialised because is_zeroed==1 above) // unfortunately not identified as being in a free'd // block because the freeing of the block and shadow // chunk isn't postponed. // leak from make_leak() }
int main(void) { int *array, *array3; int x; array = custom_alloc(sizeof(int) * 10); array[8] = 8; array[9] = 8; array[10] = 10; // invalid write (ok w/o MALLOCLIKE -- in superblock) VALGRIND_RESIZEINPLACE_BLOCK(array, sizeof(int) * 10, sizeof(int) * 5, RZ); array[4] = 7; array[5] = 9; // invalid write // Make the entire array defined again such that it can be verified whether // the red zone is marked properly when resizing in place. VALGRIND_MAKE_MEM_DEFINED(array, sizeof(int) * 10); VALGRIND_RESIZEINPLACE_BLOCK(array, sizeof(int) * 5, sizeof(int) * 7, RZ); if (array[5]) array[4]++; // uninitialized read of array[5] array[5] = 11; array[6] = 7; array[7] = 8; // invalid write // invalid realloc VALGRIND_RESIZEINPLACE_BLOCK(array+1, sizeof(int) * 7, sizeof(int) * 8, RZ); custom_free(array); // ok custom_free((void*)0x1); // invalid free array3 = malloc(sizeof(int) * 10); custom_free(array3); // mismatched free (ok without MALLOCLIKE) make_leak(); x = array[0]; // use after free (ok without MALLOCLIKE/MAKE_MEM_NOACCESS) // (nb: initialised because is_zeroed==1 above) // unfortunately not identified as being in a free'd // block because the freeing of the block and shadow // chunk isn't postponed. // Bug 137073: passing 0 to MALLOCLIKE_BLOCK was causing an assertion // failure. Test for this (and likewise for FREELIKE_BLOCK). VALGRIND_MALLOCLIKE_BLOCK(0,0,0,0); VALGRIND_FREELIKE_BLOCK(0,0); return x; // leak from make_leak() }
TEST_F(MallocTests, CheckManySmallAllocations) { const size_t alloc_sz = 256; const size_t arr_sz = 4096; char* small_ptrs[arr_sz]; for (uint64_t i = 0; i < arr_sz; i++) { small_ptrs[i] = (char*) custom_malloc(sizeof(char) * alloc_sz); ASSERT_NE(small_ptrs[i], (void*) NULL); memset(&small_ptrs[i][0], (char) i % 255, alloc_sz); } for (uint64_t i = 0; i < arr_sz; i++) { ASSERT_NE(small_ptrs[i], (void*) NULL); for (uint64_t j = 0; j < alloc_sz; j++) { char target = (char) i % 255; ASSERT_EQ(small_ptrs[i][j], target) << "Failed at iteration [" << i << "] at offset [" << j << "]."; } } for (uint64_t i = 0; i < arr_sz; i++) { custom_free(small_ptrs[i]); } }
void parallel_test_work() { const int rand_sz = 4096 * 1; const size_t arr_sz = 256; char* small_ptrs[arr_sz]; size_t small_ptrs_sz[arr_sz]; for (uint64_t i = 0; i < arr_sz; i++) { small_ptrs_sz[i] = rand() % rand_sz; small_ptrs[i] = (char*) custom_malloc(sizeof(char) * small_ptrs_sz[i]); ASSERT_NE(small_ptrs[i], (void*) NULL); memset(&small_ptrs[i][0], (char) i % 255, small_ptrs_sz[i]); } for (uint64_t i = 0; i < arr_sz; i++) { ASSERT_NE(small_ptrs[i], (void*) NULL); for (uint64_t j = 0; j < small_ptrs_sz[i]; j++) { char target = (char) i % 255; ASSERT_EQ(small_ptrs[i][j], target) << "Failed at iteration [" << i << "] at offset [" << j << "]."; } } for (uint64_t i = 0; i < arr_sz; i++) { custom_free(small_ptrs[i]); } return; }
void free(void * pointer) { void (* libc_free)(void *) = (void (*)(void *))dlsym(RTLD_NEXT, "free"); if (enabled.load()) { return custom_free(pointer); } return libc_free(pointer); }
TEST_F(MallocTests, SimpleMalloc) { char* ptr = (char*) custom_malloc(sizeof(char) * 16); ASSERT_NE(ptr, (void *) NULL); ASSERT_EQ(custom_malloc_usable_size(ptr), static_cast<size_t>(16)); memset(ptr, 'A', 15); ptr[15] = 0; ASSERT_EQ(strcmp(ptr, "AAAAAAAAAAAAAAA"), 0); custom_free(ptr); }
TEST_F(MallocTests, MediumMalloc) { int sz = 4312; char* ptr = (char*) custom_malloc(sz); ASSERT_TRUE(ptr != NULL); for (int i = 0; i < sz; i++) ptr[i] = 33 + (i % 126 - 33); for (int i = 0; i < sz; i++) ASSERT_EQ(ptr[i], 33 + (i % 126 - 33)); custom_free(ptr); }
TEST_F(MallocTests, ManyAllocations) { int MANY = 1000; char* ptr = NULL; for (int i = 0; i < MANY; i++) { ptr = (char*) custom_malloc(256); ASSERT_TRUE(ptr != NULL); memset(ptr, 'A', 256); custom_free(ptr); } }
TEST_F(MallocTests, RandomAllocations) { void* ptr = NULL; for (int i = 0; i < 4096; i++) { int sz = rand() % 4096; ptr = custom_malloc(sz); ASSERT_NE(ptr, (void*) NULL); ASSERT_GE(custom_malloc_usable_size(ptr), static_cast<size_t>(sz)); custom_free(ptr); } }
TEST_F(MallocTests, ReuseOldAllocations) { char* ptr; char* _ptr = NULL; for (int i = 0; i < 8; i++) { ptr = (char*) custom_malloc(64); ASSERT_TRUE(ptr != NULL); if (_ptr) ASSERT_EQ(_ptr, ptr) << "Failure on iteration [" << i << "]"; memset(ptr, 'A', 64); custom_free(ptr); _ptr = ptr; } ptr = (char*) custom_malloc(156); ASSERT_TRUE(ptr != NULL); ASSERT_NE(ptr, _ptr); ASSERT_GE(custom_malloc_usable_size(ptr), static_cast<size_t>(156)); custom_free(ptr); }
TEST_F(MallocTests, ManyMalloc) { char* ptr; for (int i = 0; i < 4096; i++) { ptr = (char*) custom_malloc(32); ASSERT_TRUE(ptr != NULL); for (int j = 0; j < 32; j++) ptr[j] = 'A'; for (int j = 0; j < 32; j++) ASSERT_EQ(ptr[j], 'A'); custom_free(ptr); } }
TEST_F(MallocTests, BigMalloc) { // A size allocated by the Python interpreter during compilation of Python // 3.3 that causes weird deadlock int sz = 91424; char* ptr = (char*) custom_malloc(sz); ASSERT_TRUE(ptr != NULL); for (int i = 0; i < sz; i++) ptr[i] = 33 + (i % 126 - 33); for (int i = 0; i < sz; i++) ASSERT_EQ(ptr[i], 33 + (i % 126 - 33)); custom_free(ptr); }
TEST_F(MallocTests, ReuseAllocation) { char* ptr1 = NULL; char* ptr2 = NULL; ptr1 = (char*) custom_malloc(128); memset(ptr1, 'A', 64); custom_free(ptr1); ptr2 = (char*) custom_malloc(16); memset(ptr2, 'B', 16); ASSERT_EQ(ptr1, ptr2); }
TEST_F(MallocTests, ManyReallocs) { char* ptr = NULL; char* new_ptr = NULL; size_t sz = 16; size_t max_sz = 1024; ptr = (char*) custom_malloc(sizeof(char) * 16); memset(ptr, 'A', 16); for (uint64_t i = 1; i <= max_sz - sz; i++) { new_ptr = (char*) custom_realloc(ptr, sz + i); ASSERT_NE(new_ptr, (void*) NULL); memset(new_ptr, 'A', sz + i); ptr = new_ptr; } ASSERT_EQ(custom_malloc_usable_size(ptr), max_sz); custom_free(ptr); }
WEAK void halide_free(void *user_context, void *ptr) { custom_free(user_context, ptr); }