diff options
Diffstat (limited to 'intern/guardedalloc')
-rw-r--r-- | intern/guardedalloc/CMakeLists.txt | 16 | ||||
-rw-r--r-- | intern/guardedalloc/MEM_guardedalloc.h | 2 | ||||
-rw-r--r-- | intern/guardedalloc/intern/leak_detector.cc | 2 | ||||
-rw-r--r-- | intern/guardedalloc/intern/mallocn_guarded_impl.c | 21 | ||||
-rw-r--r-- | intern/guardedalloc/intern/mallocn_lockfree_impl.c | 10 | ||||
-rw-r--r-- | intern/guardedalloc/intern/mmap_win.c | 43 | ||||
-rw-r--r-- | intern/guardedalloc/tests/guardedalloc_alignment_test.cc | 121 | ||||
-rw-r--r-- | intern/guardedalloc/tests/guardedalloc_overflow_test.cc | 65 |
8 files changed, 245 insertions, 35 deletions
diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt index 1ab365a376a..ccc1500c014 100644 --- a/intern/guardedalloc/CMakeLists.txt +++ b/intern/guardedalloc/CMakeLists.txt @@ -78,3 +78,19 @@ if(WITH_CXX_GUARDEDALLOC) ) blender_add_lib(bf_intern_guardedalloc_cpp "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") endif() + +if(WITH_GTESTS) + set(TEST_SRC + tests/guardedalloc_alignment_test.cc + tests/guardedalloc_overflow_test.cc + ) + set(TEST_INC + ../../source/blender/blenlib + ) + set(TEST_LIB + bf_intern_guardedalloc + bf_blenlib + ) + include(GTestTesting) + blender_add_test_lib(bf_intern_guardedalloc_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}") +endif() diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index 604330bd1d3..9c62b2396f6 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -213,7 +213,7 @@ extern const char *(*MEM_name_ptr)(void *vmemh); /** This should be called as early as possible in the program. When it has been called, information * about memory leaks will be printed on exit. */ -void MEM_initialize_memleak_detection(void); +void MEM_init_memleak_detection(void); /* Switch allocator to slower but fully guarded mode. */ void MEM_use_guarded_allocator(void); diff --git a/intern/guardedalloc/intern/leak_detector.cc b/intern/guardedalloc/intern/leak_detector.cc index 4b2689ee28c..d7b6f749742 100644 --- a/intern/guardedalloc/intern/leak_detector.cc +++ b/intern/guardedalloc/intern/leak_detector.cc @@ -46,7 +46,7 @@ class MemLeakPrinter { }; } // namespace -void MEM_initialize_memleak_detection(void) +void MEM_init_memleak_detection(void) { /** * This variable is constructed when this function is first called. This should happen as soon as diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c index 2c207935e43..6c08cb3bb62 100644 --- a/intern/guardedalloc/intern/mallocn_guarded_impl.c +++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c @@ -249,9 +249,8 @@ size_t MEM_guarded_allocN_len(const void *vmemh) memh--; return memh->len; } - else { - return 0; - } + + return 0; } void *MEM_guarded_dupallocN(const void *vmemh) @@ -611,12 +610,11 @@ static int compare_len(const void *p1, const void *p2) if (pb1->len < pb2->len) { return 1; } - else if (pb1->len == pb2->len) { + if (pb1->len == pb2->len) { return 0; } - else { - return -1; - } + + return -1; } void MEM_guarded_printmemlist_stats(void) @@ -682,7 +680,7 @@ void MEM_guarded_printmemlist_stats(void) if (a == b) { continue; } - else if (strcmp(printblock[a].name, printblock[b].name) == 0) { + if (strcmp(printblock[a].name, printblock[b].name) == 0) { printblock[b].len += printblock[a].len; printblock[b].items++; } @@ -1162,7 +1160,7 @@ static const char *check_memlist(MemHead *memh) return ("Additional error in header"); } - return (name); + return name; } size_t MEM_guarded_get_peak_memory(void) @@ -1213,8 +1211,7 @@ const char *MEM_guarded_name_ptr(void *vmemh) memh--; return memh->name; } - else { - return "MEM_guarded_name_ptr(NULL)"; - } + + return "MEM_guarded_name_ptr(NULL)"; } #endif /* NDEBUG */ diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c index b71e2c963eb..8f5c9cf85a9 100644 --- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c +++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c @@ -94,9 +94,8 @@ size_t MEM_lockfree_allocN_len(const void *vmemh) if (vmemh) { return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_ALIGN_FLAG)); } - else { - return 0; - } + + return 0; } void MEM_lockfree_freeN(void *vmemh) @@ -436,8 +435,7 @@ const char *MEM_lockfree_name_ptr(void *vmemh) if (vmemh) { return "unknown block name ptr"; } - else { - return "MEM_lockfree_name_ptr(NULL)"; - } + + return "MEM_lockfree_name_ptr(NULL)"; } #endif /* NDEBUG */ diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c index 245fe05b6af..a02a0f88fa9 100644 --- a/intern/guardedalloc/intern/mmap_win.c +++ b/intern/guardedalloc/intern/mmap_win.c @@ -138,10 +138,12 @@ void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t o ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0); if (ptr == NULL) { DWORD dwLastErr = GetLastError(); - if (dwLastErr == ERROR_MAPPED_ALIGNMENT) + if (dwLastErr == ERROR_MAPPED_ALIGNMENT) { errno = EINVAL; - else + } + else { errno = EACCES; + } CloseHandle(maphandle); return MAP_FAILED; } @@ -182,18 +184,22 @@ static void mmap_addtail(volatile mmapListBase *listbase, void *vlink) { struct mmapLink *link = vlink; - if (link == NULL) + if (link == NULL) { return; - if (listbase == NULL) + } + if (listbase == NULL) { return; + } link->next = 0; link->prev = listbase->last; - if (listbase->last) + if (listbase->last) { ((struct mmapLink *)listbase->last)->next = link; - if (listbase->first == NULL) + } + if (listbase->first == NULL) { listbase->first = link; + } listbase->last = link; } @@ -201,30 +207,37 @@ static void mmap_remlink(volatile mmapListBase *listbase, void *vlink) { struct mmapLink *link = vlink; - if (link == NULL) + if (link == NULL) { return; - if (listbase == NULL) + } + if (listbase == NULL) { return; - - if (link->next) + } + if (link->next) { link->next->prev = link->prev; - if (link->prev) + } + if (link->prev) { link->prev->next = link->next; + } - if (listbase->last == link) + if (listbase->last == link) { listbase->last = link->prev; - if (listbase->first == link) + } + if (listbase->first == link) { listbase->first = link->next; + } } static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr) { MemMap *mm; - if (ptr == NULL) + if (ptr == NULL) { return NULL; - if (listbase == NULL) + } + if (listbase == NULL) { return NULL; + } mm = (MemMap *)listbase->first; while (mm) { diff --git a/intern/guardedalloc/tests/guardedalloc_alignment_test.cc b/intern/guardedalloc/tests/guardedalloc_alignment_test.cc new file mode 100644 index 00000000000..4c676c6cc76 --- /dev/null +++ b/intern/guardedalloc/tests/guardedalloc_alignment_test.cc @@ -0,0 +1,121 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" + +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ((size_t)ptr % align, 0) + +namespace { + +void DoBasicAlignmentChecks(const int alignment) +{ + int *foo, *bar; + + foo = (int *)MEM_mallocN_aligned(sizeof(int) * 10, alignment, "test"); + CHECK_ALIGNMENT(foo, alignment); + + bar = (int *)MEM_dupallocN(foo); + CHECK_ALIGNMENT(bar, alignment); + MEM_freeN(bar); + + foo = (int *)MEM_reallocN(foo, sizeof(int) * 5); + CHECK_ALIGNMENT(foo, alignment); + + foo = (int *)MEM_recallocN(foo, sizeof(int) * 5); + CHECK_ALIGNMENT(foo, alignment); + + MEM_freeN(foo); +} + +} // namespace + +TEST(guardedalloc, LockfreeAlignedAlloc1) +{ + DoBasicAlignmentChecks(1); +} + +TEST(guardedalloc, GuardedAlignedAlloc1) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(1); +} + +TEST(guardedalloc, LockfreeAlignedAlloc2) +{ + DoBasicAlignmentChecks(2); +} + +TEST(guardedalloc, GuardedAlignedAlloc2) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(2); +} + +TEST(guardedalloc, LockfreeAlignedAlloc4) +{ + DoBasicAlignmentChecks(4); +} + +TEST(guardedalloc, GuardedAlignedAlloc4) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(4); +} + +TEST(guardedalloc, LockfreeAlignedAlloc8) +{ + DoBasicAlignmentChecks(8); +} + +TEST(guardedalloc, GuardedAlignedAlloc8) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(8); +} + +TEST(guardedalloc, LockfreeAlignedAlloc16) +{ + DoBasicAlignmentChecks(16); +} + +TEST(guardedalloc, GuardedAlignedAlloc16) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(16); +} + +TEST(guardedalloc, LockfreeAlignedAlloc32) +{ + DoBasicAlignmentChecks(32); +} + +TEST(guardedalloc, GuardedAlignedAlloc32) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(32); +} + +TEST(guardedalloc, LockfreeAlignedAlloc256) +{ + DoBasicAlignmentChecks(256); +} + +TEST(guardedalloc, GuardedAlignedAlloc256) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(256); +} + +TEST(guardedalloc, LockfreeAlignedAlloc512) +{ + DoBasicAlignmentChecks(512); +} + +TEST(guardedalloc, GuardedAlignedAlloc512) +{ + MEM_use_guarded_allocator(); + DoBasicAlignmentChecks(512); +} diff --git a/intern/guardedalloc/tests/guardedalloc_overflow_test.cc b/intern/guardedalloc/tests/guardedalloc_overflow_test.cc new file mode 100644 index 00000000000..eb9a2a68cb0 --- /dev/null +++ b/intern/guardedalloc/tests/guardedalloc_overflow_test.cc @@ -0,0 +1,65 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" + +#include "MEM_guardedalloc.h" + +/* We expect to abort on integer overflow, to prevent possible exploits. */ +#ifdef _WIN32 +# define ABORT_PREDICATE ::testing::ExitedWithCode(3) +#else +# define ABORT_PREDICATE ::testing::KilledBySignal(SIGABRT) +#endif + +#ifdef __GNUC__ +/* Disable since it's the purpose of this test. */ +# pragma GCC diagnostic ignored "-Walloc-size-larger-than=" +#endif + +namespace { + +void MallocArray(size_t len, size_t size) +{ + void *mem = MEM_malloc_arrayN(len, size, "MallocArray"); + if (mem) { + MEM_freeN(mem); + } +} + +void CallocArray(size_t len, size_t size) +{ + void *mem = MEM_calloc_arrayN(len, size, "CallocArray"); + if (mem) { + MEM_freeN(mem); + } +} + +} // namespace + +TEST(guardedalloc, LockfreeIntegerOverflow) +{ + MallocArray(1, SIZE_MAX); + CallocArray(SIZE_MAX, 1); + MallocArray(SIZE_MAX / 2, 2); + CallocArray(SIZE_MAX / 1234567, 1234567); + + EXPECT_EXIT(MallocArray(SIZE_MAX, 2), ABORT_PREDICATE, ""); + EXPECT_EXIT(CallocArray(7, SIZE_MAX), ABORT_PREDICATE, ""); + EXPECT_EXIT(MallocArray(SIZE_MAX, 12345567), ABORT_PREDICATE, ""); + EXPECT_EXIT(CallocArray(SIZE_MAX, SIZE_MAX), ABORT_PREDICATE, ""); +} + +TEST(guardedalloc, GuardedIntegerOverflow) +{ + MEM_use_guarded_allocator(); + + MallocArray(1, SIZE_MAX); + CallocArray(SIZE_MAX, 1); + MallocArray(SIZE_MAX / 2, 2); + CallocArray(SIZE_MAX / 1234567, 1234567); + + EXPECT_EXIT(MallocArray(SIZE_MAX, 2), ABORT_PREDICATE, ""); + EXPECT_EXIT(CallocArray(7, SIZE_MAX), ABORT_PREDICATE, ""); + EXPECT_EXIT(MallocArray(SIZE_MAX, 12345567), ABORT_PREDICATE, ""); + EXPECT_EXIT(CallocArray(SIZE_MAX, SIZE_MAX), ABORT_PREDICATE, ""); +} |