summaryrefslogtreecommitdiff
path: root/test/scudo
diff options
context:
space:
mode:
authorKostya Kortchinsky <kostyak@google.com>2017-02-03 20:49:42 +0000
committerKostya Kortchinsky <kostyak@google.com>2017-02-03 20:49:42 +0000
commit044cfea04848ec011bb35575a28dfb0165db85cf (patch)
tree5b28c0d65bf4931631912d3c13cc47100aeee156 /test/scudo
parentc38680b2e6f08700b52826931c7cd3cea0380d75 (diff)
[scudo] 32-bit quarantine sizes adjustments and bug fixes
Summary: The local and global quarantine sizes were not offering a distinction for 32-bit and 64-bit platforms. This is addressed with lower values for 32-bit. When writing additional tests for the quarantine, it was discovered that when calling some of the allocator interface function prior to any allocation operation having occured, the test would crash due to the allocator not being initialized. This was addressed by making sure the allocator is initialized for those scenarios. Relevant tests were added in interface.cpp and quarantine.cpp. Last change being the removal of the extraneous link dependencies for the tests thanks to rL293220, anf the addition of the gc-sections linker flag. Reviewers: kcc, alekseyshl Reviewed By: alekseyshl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D29341 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@294037 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/scudo')
-rw-r--r--test/scudo/alignment.cpp3
-rw-r--r--test/scudo/double-free.cpp12
-rw-r--r--test/scudo/interface.cpp45
-rw-r--r--test/scudo/lit.cfg6
-rw-r--r--test/scudo/malloc.cpp7
-rw-r--r--test/scudo/memalign.cpp12
-rw-r--r--test/scudo/mismatch.cpp11
-rw-r--r--test/scudo/options.cpp6
-rw-r--r--test/scudo/overflow.cpp10
-rw-r--r--test/scudo/preinit.cpp5
-rw-r--r--test/scudo/quarantine.cpp62
-rw-r--r--test/scudo/realloc.cpp25
-rw-r--r--test/scudo/secondary.cpp7
-rw-r--r--test/scudo/sized-delete.cpp3
-rw-r--r--test/scudo/sizes.cpp21
15 files changed, 120 insertions, 115 deletions
diff --git a/test/scudo/alignment.cpp b/test/scudo/alignment.cpp
index a6eca87a8..125ad8cbe 100644
--- a/test/scudo/alignment.cpp
+++ b/test/scudo/alignment.cpp
@@ -14,8 +14,7 @@ int main(int argc, char **argv)
assert(argc == 2);
if (!strcmp(argv[1], "pointers")) {
void *p = malloc(1U << 16);
- if (!p)
- return 1;
+ assert(p);
free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) | 1));
}
return 0;
diff --git a/test/scudo/double-free.cpp b/test/scudo/double-free.cpp
index 75919f0c4..ddc520505 100644
--- a/test/scudo/double-free.cpp
+++ b/test/scudo/double-free.cpp
@@ -16,30 +16,26 @@ int main(int argc, char **argv)
assert(argc == 2);
if (!strcmp(argv[1], "malloc")) {
void *p = malloc(sizeof(int));
- if (!p)
- return 1;
+ assert(p);
free(p);
free(p);
}
if (!strcmp(argv[1], "new")) {
int *p = new int;
- if (!p)
- return 1;
+ assert(p);
delete p;
delete p;
}
if (!strcmp(argv[1], "newarray")) {
int *p = new int[8];
- if (!p)
- return 1;
+ assert(p);
delete[] p;
delete[] p;
}
if (!strcmp(argv[1], "memalign")) {
void *p = nullptr;
posix_memalign(&p, 0x100, sizeof(int));
- if (!p)
- return 1;
+ assert(p);
free(p);
free(p);
}
diff --git a/test/scudo/interface.cpp b/test/scudo/interface.cpp
index 55de17432..c5a887780 100644
--- a/test/scudo/interface.cpp
+++ b/test/scudo/interface.cpp
@@ -1,9 +1,13 @@
// RUN: %clang_scudo %s -lstdc++ -o %t
-// RUN: %run %t 2>&1
+// RUN: %run %t ownership 2>&1
+// RUN: %run %t ownership-and-size 2>&1
+// RUN: %run %t heap-size 2>&1
// Tests that the sanitizer interface functions behave appropriately.
#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
#include <vector>
@@ -11,18 +15,33 @@
int main(int argc, char **argv)
{
- void *p;
- std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
- 1 << 16, 1 << 17, 1 << 20, 1 << 24};
- for (size_t size : sizes) {
- p = malloc(size);
- if (!p)
- return 1;
- if (!__sanitizer_get_ownership(p))
- return 1;
- if (__sanitizer_get_allocated_size(p) < size)
- return 1;
- free(p);
+ assert(argc == 2);
+
+ if (!strcmp(argv[1], "ownership")) {
+ // Ensures that __sanitizer_get_ownership can be called before any other
+ // allocator function, and that it behaves properly on a pointer not owned
+ // by us.
+ assert(!__sanitizer_get_ownership(argv));
+ }
+ if (!strcmp(argv[1], "ownership-and-size")) {
+ // Tests that __sanitizer_get_ownership and __sanitizer_get_allocated_size
+ // behave properly on chunks allocated by the Primary and Secondary.
+ void *p;
+ std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
+ 1 << 16, 1 << 17, 1 << 20, 1 << 24};
+ for (size_t size : sizes) {
+ p = malloc(size);
+ assert(p);
+ assert(__sanitizer_get_ownership(p));
+ assert(__sanitizer_get_allocated_size(p) >= size);
+ free(p);
+ }
}
+ if (!strcmp(argv[1], "heap-size")) {
+ // Ensures that __sanitizer_get_heap_size can be called before any other
+ // allocator function. At this point, this heap size should be 0.
+ assert(__sanitizer_get_heap_size() == 0);
+ }
+
return 0;
}
diff --git a/test/scudo/lit.cfg b/test/scudo/lit.cfg
index b0476303c..0fa44087e 100644
--- a/test/scudo/lit.cfg
+++ b/test/scudo/lit.cfg
@@ -19,12 +19,12 @@ config.suffixes = ['.c', '.cc', '.cpp']
# C flags.
c_flags = ([config.target_cflags] +
["-std=c++11",
- "-lrt",
- "-ldl",
"-pthread",
"-fPIE",
"-pie",
- "-O0"])
+ "-O0",
+ "-UNDEBUG",
+ "-Wl,--gc-sections"])
def build_invocation(compile_flags):
return " " + " ".join([config.clang] + compile_flags) + " "
diff --git a/test/scudo/malloc.cpp b/test/scudo/malloc.cpp
index fbe57a8cb..50e52590f 100644
--- a/test/scudo/malloc.cpp
+++ b/test/scudo/malloc.cpp
@@ -5,6 +5,7 @@
// intended. Tests various sizes serviced by the primary and secondary
// allocators.
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -18,8 +19,7 @@ int main(int argc, char **argv)
std::vector<int> offsets{1, 0, -1, -7, -8, -15, -16, -31, -32};
p = malloc(0);
- if (!p)
- return 1;
+ assert(p);
free(p);
for (ssize_t size : sizes) {
for (int offset: offsets) {
@@ -27,8 +27,7 @@ int main(int argc, char **argv)
if (actual_size <= 0)
continue;
p = malloc(actual_size);
- if (!p)
- return 1;
+ assert(p);
memset(p, 0xff, actual_size);
free(p);
}
diff --git a/test/scudo/memalign.cpp b/test/scudo/memalign.cpp
index b407ec574..c263da75e 100644
--- a/test/scudo/memalign.cpp
+++ b/test/scudo/memalign.cpp
@@ -29,12 +29,10 @@ int main(int argc, char **argv)
if (!strcmp(argv[1], "valid")) {
posix_memalign(&p, alignment, size);
- if (!p)
- return 1;
+ assert(p);
free(p);
p = aligned_alloc(alignment, size);
- if (!p)
- return 1;
+ assert(p);
free(p);
// Tests various combinations of alignment and sizes
for (int i = (sizeof(void *) == 4) ? 3 : 4; i < 19; i++) {
@@ -43,8 +41,7 @@ int main(int argc, char **argv)
size = 0x800 * j;
for (int k = 0; k < 3; k++) {
p = memalign(alignment, size - (2 * sizeof(void *) * k));
- if (!p)
- return 1;
+ assert(p);
free(p);
}
}
@@ -54,8 +51,7 @@ int main(int argc, char **argv)
for (int i = 19; i <= 24; i++) {
for (int k = 0; k < 3; k++) {
p = memalign(alignment, 0x1000 - (2 * sizeof(void *) * k));
- if (!p)
- return 1;
+ assert(p);
free(p);
}
}
diff --git a/test/scudo/mismatch.cpp b/test/scudo/mismatch.cpp
index 54cdafc86..15dce83ce 100644
--- a/test/scudo/mismatch.cpp
+++ b/test/scudo/mismatch.cpp
@@ -10,29 +10,26 @@
// caught when the related option is set.
#include <assert.h>
+#include <malloc.h>
#include <stdlib.h>
#include <string.h>
-#include <malloc.h>
int main(int argc, char **argv)
{
assert(argc == 2);
if (!strcmp(argv[1], "mallocdel")) {
int *p = (int *)malloc(16);
- if (!p)
- return 1;
+ assert(p);
delete p;
}
if (!strcmp(argv[1], "newfree")) {
int *p = new int;
- if (!p)
- return 1;
+ assert(p);
free((void *)p);
}
if (!strcmp(argv[1], "memaligndel")) {
int *p = (int *)memalign(16, 16);
- if (!p)
- return 1;
+ assert(p);
delete p;
}
return 0;
diff --git a/test/scudo/options.cpp b/test/scudo/options.cpp
index bccf7c8fb..f4afe7d79 100644
--- a/test/scudo/options.cpp
+++ b/test/scudo/options.cpp
@@ -6,8 +6,9 @@
// Tests that the options can be passed using getScudoDefaultOptions, and that
// the environment ones take precedence over them.
-#include <stdlib.h>
+#include <assert.h>
#include <malloc.h>
+#include <stdlib.h>
extern "C" const char* __scudo_default_options() {
return "DeallocationTypeMismatch=0"; // Defaults to true in scudo_flags.inc.
@@ -16,8 +17,7 @@ extern "C" const char* __scudo_default_options() {
int main(int argc, char **argv)
{
int *p = (int *)malloc(16);
- if (!p)
- return 1;
+ assert(p);
delete p;
return 0;
}
diff --git a/test/scudo/overflow.cpp b/test/scudo/overflow.cpp
index c93a544ea..d12824578 100644
--- a/test/scudo/overflow.cpp
+++ b/test/scudo/overflow.cpp
@@ -10,20 +10,20 @@
int main(int argc, char **argv)
{
- assert(argc == 2);
ssize_t offset = sizeof(void *) == 8 ? 8 : 0;
+
+ assert(argc == 2);
+
if (!strcmp(argv[1], "malloc")) {
// Simulate a header corruption of an allocated chunk (1-bit)
void *p = malloc(1U << 4);
- if (!p)
- return 1;
+ assert(p);
((char *)p)[-(offset + 1)] ^= 1;
free(p);
}
if (!strcmp(argv[1], "quarantine")) {
void *p = malloc(1U << 4);
- if (!p)
- return 1;
+ assert(p);
free(p);
// Simulate a header corruption of a quarantined chunk
((char *)p)[-(offset + 2)] ^= 1;
diff --git a/test/scudo/preinit.cpp b/test/scudo/preinit.cpp
index 34f61c9dd..b8c01a401 100644
--- a/test/scudo/preinit.cpp
+++ b/test/scudo/preinit.cpp
@@ -4,6 +4,7 @@
// Verifies that calling malloc in a preinit_array function succeeds, and that
// the resulting pointer can be freed at program termination.
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -23,8 +24,7 @@ void __fini(void) {
int main(int argc, char **argv)
{
void *p = malloc(1);
- if (!p)
- return 1;
+ assert(p);
free(p);
return 0;
@@ -34,4 +34,3 @@ __attribute__((section(".preinit_array"), used))
void (*__local_preinit)(void) = __init;
__attribute__((section(".fini_array"), used))
void (*__local_fini)(void) = __fini;
-
diff --git a/test/scudo/quarantine.cpp b/test/scudo/quarantine.cpp
index 4ce0197ac..39ce1bd91 100644
--- a/test/scudo/quarantine.cpp
+++ b/test/scudo/quarantine.cpp
@@ -1,43 +1,57 @@
// RUN: %clang_scudo %s -o %t
-// RUN: SCUDO_OPTIONS=QuarantineSizeMb=1 %run %t 2>&1
+// RUN: SCUDO_OPTIONS="QuarantineSizeMb=0:ThreadLocalQuarantineSizeKb=0" %run %t zeroquarantine 2>&1
+// RUN: SCUDO_OPTIONS=QuarantineSizeMb=1 %run %t smallquarantine 2>&1
// Tests that the quarantine prevents a chunk from being reused right away.
// Also tests that a chunk will eventually become available again for
// allocation when the recycling criteria has been met.
+#include <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
+#include <sanitizer/allocator_interface.h>
+
int main(int argc, char **argv)
{
void *p, *old_p;
- size_t size = 1U << 16;
-
- // The delayed freelist will prevent a chunk from being available right away
- p = malloc(size);
- if (!p)
- return 1;
- old_p = p;
- free(p);
- p = malloc(size);
- if (!p)
- return 1;
- if (old_p == p)
- return 1;
- free(p);
-
- // Eventually the chunk should become available again
- bool found = false;
- for (int i = 0; i < 0x100 && found == false; i++) {
+ size_t allocated_bytes, size = 1U << 16;
+
+ assert(argc == 2);
+
+ if (!strcmp(argv[1], "zeroquarantine")) {
+ // Verifies that a chunk is deallocated right away when the local and
+ // global quarantine sizes are 0.
+ allocated_bytes = __sanitizer_get_current_allocated_bytes();
p = malloc(size);
- if (!p)
- return 1;
- found = (p == old_p);
+ assert(p);
+ assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
free(p);
+ assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
+ }
+ if (!strcmp(argv[1], "smallquarantine")) {
+ // The delayed freelist will prevent a chunk from being available right
+ // away.
+ p = malloc(size);
+ assert(p);
+ old_p = p;
+ free(p);
+ p = malloc(size);
+ assert(p);
+ assert(old_p != p);
+ free(p);
+
+ // Eventually the chunk should become available again.
+ bool found = false;
+ for (int i = 0; i < 0x100 && found == false; i++) {
+ p = malloc(size);
+ assert(p);
+ found = (p == old_p);
+ free(p);
+ }
+ assert(found == true);
}
- if (found == false)
- return 1;
return 0;
}
diff --git a/test/scudo/realloc.cpp b/test/scudo/realloc.cpp
index d34e356fb..da377205f 100644
--- a/test/scudo/realloc.cpp
+++ b/test/scudo/realloc.cpp
@@ -23,48 +23,41 @@ int main(int argc, char **argv)
std::vector<size_t> sizes{1, 16, 1024, 32768, 1 << 16, 1 << 17, 1 << 20};
assert(argc == 2);
+
for (size_t size : sizes) {
if (!strcmp(argv[1], "pointers")) {
old_p = p = realloc(nullptr, size);
- if (!p)
- return 1;
+ assert(p);
size = malloc_usable_size(p);
// Our realloc implementation will return the same pointer if the size
// requested is lower than or equal to the usable size of the associated
// chunk.
p = realloc(p, size - 1);
- if (p != old_p)
- return 1;
+ assert(p == old_p);
p = realloc(p, size);
- if (p != old_p)
- return 1;
+ assert(p == old_p);
// And a new one if the size is greater.
p = realloc(p, size + 1);
- if (p == old_p)
- return 1;
+ assert(p != old_p);
// A size of 0 will free the chunk and return nullptr.
p = realloc(p, 0);
- if (p)
- return 1;
+ assert(!p);
old_p = nullptr;
}
if (!strcmp(argv[1], "contents")) {
p = realloc(nullptr, size);
- if (!p)
- return 1;
+ assert(p);
for (int i = 0; i < size; i++)
reinterpret_cast<char *>(p)[i] = 'A';
p = realloc(p, size + 1);
// The contents of the reallocated chunk must match the original one.
for (int i = 0; i < size; i++)
- if (reinterpret_cast<char *>(p)[i] != 'A')
- return 1;
+ assert(reinterpret_cast<char *>(p)[i] == 'A');
}
if (!strcmp(argv[1], "memalign")) {
// A chunk coming from memalign cannot be reallocated.
p = memalign(16, size);
- if (!p)
- return 1;
+ assert(p);
p = realloc(p, size);
free(p);
}
diff --git a/test/scudo/secondary.cpp b/test/scudo/secondary.cpp
index 7a634a81e..dc14f8ca8 100644
--- a/test/scudo/secondary.cpp
+++ b/test/scudo/secondary.cpp
@@ -5,12 +5,12 @@
// Test that we hit a guard page when writing past the end of a chunk
// allocated by the Secondary allocator, or writing too far in front of it.
+#include <assert.h>
#include <malloc.h>
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <signal.h>
-#include <assert.h>
void handler(int signo, siginfo_t *info, void *uctx) {
if (info->si_code == SEGV_ACCERR) {
@@ -33,8 +33,7 @@ int main(int argc, char **argv)
a.sa_flags = SA_SIGINFO;
char *p = (char *)malloc(size);
- if (!p)
- return 1;
+ assert(p);
memset(p, 'A', size); // This should not trigger anything.
// Set up the SIGSEGV handler now, as the rest should trigger an AV.
sigaction(SIGSEGV, &a, nullptr);
diff --git a/test/scudo/sized-delete.cpp b/test/scudo/sized-delete.cpp
index 5b1bf5fd4..e467f5565 100644
--- a/test/scudo/sized-delete.cpp
+++ b/test/scudo/sized-delete.cpp
@@ -10,11 +10,12 @@
// option is passed and the sizes do not match between allocation and
// deallocation functions.
-#include <new>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <new>
+
int main(int argc, char **argv)
{
assert(argc == 2);
diff --git a/test/scudo/sizes.cpp b/test/scudo/sizes.cpp
index 7190cb64f..981b859a8 100644
--- a/test/scudo/sizes.cpp
+++ b/test/scudo/sizes.cpp
@@ -23,35 +23,28 @@ int main(int argc, char **argv)
// Currently the maximum size the allocator can allocate is 1ULL<<40 bytes.
size_t size = std::numeric_limits<size_t>::max();
void *p = malloc(size);
- if (p)
- return 1;
+ assert(!p);
size = (1ULL << 40) - 16;
p = malloc(size);
- if (p)
- return 1;
+ assert(!p);
}
if (!strcmp(argv[1], "calloc")) {
// Trigger an overflow in calloc.
size_t size = std::numeric_limits<size_t>::max();
void *p = calloc((size / 0x1000) + 1, 0x1000);
- if (p)
- return 1;
+ assert(!p);
}
if (!strcmp(argv[1], "usable")) {
// Playing with the actual usable size of a chunk.
void *p = malloc(1007);
- if (!p)
- return 1;
+ assert(p);
size_t size = malloc_usable_size(p);
- if (size < 1007)
- return 1;
+ assert(size >= 1007);
memset(p, 'A', size);
p = realloc(p, 2014);
- if (!p)
- return 1;
+ assert(p);
size = malloc_usable_size(p);
- if (size < 2014)
- return 1;
+ assert(size >= 2014);
memset(p, 'B', size);
free(p);
}