summaryrefslogtreecommitdiff
path: root/test/scudo
diff options
context:
space:
mode:
authorKostya Kortchinsky <kostyak@google.com>2016-11-30 17:32:20 +0000
committerKostya Kortchinsky <kostyak@google.com>2016-11-30 17:32:20 +0000
commit41b6e3e5d80cd78fef3a2e2b409e00ee0c77f423 (patch)
tree6b1598b6325b28c9e4f51873cadc6f4ef31aa7d1 /test/scudo
parentab8eb68f7e875f1501cdc2e5d6e70a1042d5d48c (diff)
[scudo] 32-bit and hardware agnostic support
Summary: This update introduces i386 support for the Scudo Hardened Allocator, and offers software alternatives for functions that used to require hardware specific instruction sets. This should make porting to new architectures easier. Among the changes: - The chunk header has been changed to accomodate the size limitations encountered on 32-bit architectures. We now fit everything in 64-bit. This was achieved by storing the amount of unused bytes in an allocation rather than the size itself, as one can be deduced from the other with the help of the GetActuallyAllocatedSize function. As it turns out, this header can be used for both 64 and 32 bit, and as such we dropped the requirement for the 128-bit compare and exchange instruction support (cmpxchg16b). - Add 32-bit support for the checksum and the PRNG functions: if the SSE 4.2 instruction set is supported, use the 32-bit CRC32 instruction, and in the XorShift128, use a 32-bit based state instead of 64-bit. - Add software support for CRC32: if SSE 4.2 is not supported, fallback on a software implementation. - Modify tests that were not 32-bit compliant, and expand them to cover more allocation and alignment sizes. The random shuffle test has been deactivated for linux-i386 & linux-i686 as the 32-bit sanitizer allocator doesn't currently randomize chunks. Reviewers: alekseyshl, kcc Subscribers: filcab, llvm-commits, tberghammer, danalbert, srhines, mgorny, modocache Differential Revision: https://reviews.llvm.org/D26358 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@288255 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/scudo')
-rw-r--r--test/scudo/CMakeLists.txt40
-rw-r--r--test/scudo/alignment.cpp7
-rw-r--r--test/scudo/double-free.cpp2
-rw-r--r--test/scudo/interface.cpp28
-rw-r--r--test/scudo/lit.cfg13
-rw-r--r--test/scudo/lit.site.cfg.in4
-rw-r--r--test/scudo/malloc.cpp25
-rw-r--r--test/scudo/memalign.cpp2
-rw-r--r--test/scudo/mismatch.cpp2
-rw-r--r--test/scudo/overflow.cpp5
-rw-r--r--test/scudo/preinit.cpp1
-rw-r--r--test/scudo/random_shuffle.cpp1
-rw-r--r--test/scudo/realloc.cpp2
13 files changed, 93 insertions, 39 deletions
diff --git a/test/scudo/CMakeLists.txt b/test/scudo/CMakeLists.txt
index b6cb2fd24..42cdaf9e8 100644
--- a/test/scudo/CMakeLists.txt
+++ b/test/scudo/CMakeLists.txt
@@ -1,6 +1,7 @@
set(SCUDO_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SCUDO_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+set(SCUDO_TESTSUITES)
set(SCUDO_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
@@ -12,17 +13,30 @@ configure_lit_site_cfg(
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
)
-if(CMAKE_SYSTEM_NAME MATCHES "Linux")
- EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO)
- STRING(REGEX REPLACE "^.*(sse4_2).*$" "\\1" SSE_THERE ${CPUINFO})
- STRING(COMPARE EQUAL "sse4_2" "${SSE_THERE}" SSE42_TRUE)
-endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
+set(SCUDO_TEST_ARCH ${SCUDO_SUPPORTED_ARCH})
+foreach(arch ${SCUDO_TEST_ARCH})
+ set(SCUDO_TEST_TARGET_ARCH ${arch})
+ string(TOLOWER "-${arch}" SCUDO_TEST_CONFIG_SUFFIX)
+
+ if(ANDROID OR ${arch} MATCHES "arm|aarch64")
+ # This is only true if we are cross-compiling.
+ # Build all tests with host compiler and use host tools.
+ set(SCUDO_TEST_TARGET_CFLAGS ${COMPILER_RT_TEST_COMPILER_CFLAGS})
+ else()
+ get_target_flags_for_arch(${arch} SCUDO_TEST_TARGET_CFLAGS)
+ string(REPLACE ";" " " SCUDO_TEST_TARGET_CFLAGS "${SCUDO_TEST_TARGET_CFLAGS}")
+ endif()
-if (SSE42_TRUE AND CMAKE_SIZEOF_VOID_P EQUAL 8)
- add_lit_testsuite(check-scudo
- "Running the Scudo Hardened Allocator tests"
- ${CMAKE_CURRENT_BINARY_DIR}
- DEPENDS ${SCUDO_TEST_DEPS})
- set_target_properties(check-scudo PROPERTIES FOLDER
- "Compiler-RT Misc")
-endif(SSE42_TRUE AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ string(TOUPPER ${arch} ARCH_UPPER_CASE)
+ set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config)
+
+ configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
+ list(APPEND SCUDO_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
+endforeach()
+
+add_lit_testsuite(check-scudo "Running the Scudo Hardened Allocator tests"
+ ${SCUDO_TESTSUITES}
+ DEPENDS ${SCUDO_TEST_DEPS})
+set_target_properties(check-scudo PROPERTIES FOLDER "Compiler-RT Misc")
diff --git a/test/scudo/alignment.cpp b/test/scudo/alignment.cpp
index c5e57d179..a6eca87a8 100644
--- a/test/scudo/alignment.cpp
+++ b/test/scudo/alignment.cpp
@@ -1,11 +1,10 @@
// RUN: %clang_scudo %s -o %t
// RUN: not %run %t pointers 2>&1 | FileCheck %s
-// Tests that a non-16-byte aligned pointer will trigger the associated error
-// on deallocation.
+// Tests that a non MinAlignment aligned pointer will trigger the associated
+// error on deallocation.
#include <assert.h>
-#include <malloc.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -17,7 +16,7 @@ int main(int argc, char **argv)
void *p = malloc(1U << 16);
if (!p)
return 1;
- free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) | 8));
+ 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 4f5bf0cb8..75919f0c4 100644
--- a/test/scudo/double-free.cpp
+++ b/test/scudo/double-free.cpp
@@ -46,4 +46,4 @@ int main(int argc, char **argv)
return 0;
}
-// CHECK: ERROR: invalid chunk state when deallocating address
+// CHECK: ERROR: invalid chunk state
diff --git a/test/scudo/interface.cpp b/test/scudo/interface.cpp
new file mode 100644
index 000000000..f9353066e
--- /dev/null
+++ b/test/scudo/interface.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_scudo %s -o %t
+// RUN: %run %t 2>&1
+
+// Tests that the sanitizer interface functions behave appropriately.
+
+#include <stdlib.h>
+
+#include <vector>
+
+#include <sanitizer/allocator_interface.h>
+
+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);
+ }
+ return 0;
+}
diff --git a/test/scudo/lit.cfg b/test/scudo/lit.cfg
index e2a4997dd..4eff2ce21 100644
--- a/test/scudo/lit.cfg
+++ b/test/scudo/lit.cfg
@@ -3,7 +3,7 @@
import os
# Setup config name.
-config.name = 'Scudo'
+config.name = 'Scudo' + config.name_suffix
# Setup source root.
config.test_source_root = os.path.dirname(__file__)
@@ -14,18 +14,19 @@ base_lib = os.path.join(config.compiler_rt_libdir,
whole_archive = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % base_lib
# Test suffixes.
-config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.ll', '.test']
+config.suffixes = ['.c', '.cc', '.cpp']
# C flags.
-c_flags = ["-std=c++11",
+c_flags = ([config.target_cflags] +
+ ["-std=c++11",
"-lstdc++",
- "-ldl",
"-lrt",
- "-pthread",
"-latomic",
+ "-ldl",
+ "-pthread",
"-fPIE",
"-pie",
- "-O0"]
+ "-O0"])
def build_invocation(compile_flags):
return " " + " ".join([config.clang] + compile_flags) + " "
diff --git a/test/scudo/lit.site.cfg.in b/test/scudo/lit.site.cfg.in
index 64e2fb39e..429951875 100644
--- a/test/scudo/lit.site.cfg.in
+++ b/test/scudo/lit.site.cfg.in
@@ -1,5 +1,9 @@
@LIT_SITE_CFG_IN_HEADER@
+config.name_suffix = "@SCUDO_TEST_CONFIG_SUFFIX@"
+config.target_arch = "@SCUDO_TEST_TARGET_ARCH@"
+config.target_cflags = "@SCUDO_TEST_TARGET_CFLAGS@"
+
# Load common config for all compiler-rt lit tests.
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
diff --git a/test/scudo/malloc.cpp b/test/scudo/malloc.cpp
index 0f452e360..cafc744a2 100644
--- a/test/scudo/malloc.cpp
+++ b/test/scudo/malloc.cpp
@@ -2,9 +2,9 @@
// RUN: %run %t 2>&1
// Tests that a regular workflow of allocation, memory fill and free works as
-// intended. Also tests that a zero-sized allocation succeeds.
+// intended. Tests various sizes serviced by the primary and secondary
+// allocators.
-#include <malloc.h>
#include <stdlib.h>
#include <string.h>
@@ -13,18 +13,25 @@
int main(int argc, char **argv)
{
void *p;
- std::vector<size_t> sizes{1, 1 << 5, 1 << 10, 1 << 15, 1 << 20};
+ std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
+ 1 << 16, 1 << 17, 1 << 20, 1 << 24};
+ std::vector<int> offsets{1, 0, -1, -7, -8, -15, -16, -31, -32};
p = malloc(0);
if (!p)
return 1;
free(p);
- for (size_t size : sizes) {
- p = malloc(size);
- if (!p)
- return 1;
- memset(p, 'A', size);
- free(p);
+ for (ssize_t size : sizes) {
+ for (int offset: offsets) {
+ ssize_t actual_size = size + offset;
+ if (actual_size <= 0)
+ continue;
+ p = malloc(actual_size);
+ if (!p)
+ return 1;
+ memset(p, 0xff, actual_size);
+ free(p);
+ }
}
return 0;
diff --git a/test/scudo/memalign.cpp b/test/scudo/memalign.cpp
index 3ad3fb055..6f4c50e69 100644
--- a/test/scudo/memalign.cpp
+++ b/test/scudo/memalign.cpp
@@ -31,7 +31,7 @@ int main(int argc, char **argv)
return 1;
free(p);
// Tests various combinations of alignment and sizes
- for (int i = 4; i < 20; i++) {
+ for (int i = (sizeof(void *) == 4) ? 3 : 4; i <= 24; i++) {
alignment = 1U << i;
for (int j = 1; j < 33; j++) {
size = 0x800 * j;
diff --git a/test/scudo/mismatch.cpp b/test/scudo/mismatch.cpp
index 2d3d198af..54cdafc86 100644
--- a/test/scudo/mismatch.cpp
+++ b/test/scudo/mismatch.cpp
@@ -30,7 +30,7 @@ int main(int argc, char **argv)
free((void *)p);
}
if (!strcmp(argv[1], "memaligndel")) {
- int *p = (int *)memalign(0x10, 0x10);
+ int *p = (int *)memalign(16, 16);
if (!p)
return 1;
delete p;
diff --git a/test/scudo/overflow.cpp b/test/scudo/overflow.cpp
index 5b2cb7560..c93a544ea 100644
--- a/test/scudo/overflow.cpp
+++ b/test/scudo/overflow.cpp
@@ -11,12 +11,13 @@
int main(int argc, char **argv)
{
assert(argc == 2);
+ ssize_t offset = sizeof(void *) == 8 ? 8 : 0;
if (!strcmp(argv[1], "malloc")) {
// Simulate a header corruption of an allocated chunk (1-bit)
void *p = malloc(1U << 4);
if (!p)
return 1;
- ((char *)p)[-1] ^= 1;
+ ((char *)p)[-(offset + 1)] ^= 1;
free(p);
}
if (!strcmp(argv[1], "quarantine")) {
@@ -25,7 +26,7 @@ int main(int argc, char **argv)
return 1;
free(p);
// Simulate a header corruption of a quarantined chunk
- ((char *)p)[-2] ^= 1;
+ ((char *)p)[-(offset + 2)] ^= 1;
// Trigger the quarantine recycle
for (int i = 0; i < 0x100; i++) {
p = malloc(1U << 16);
diff --git a/test/scudo/preinit.cpp b/test/scudo/preinit.cpp
index a280ae1d4..34f61c9dd 100644
--- a/test/scudo/preinit.cpp
+++ b/test/scudo/preinit.cpp
@@ -4,7 +4,6 @@
// Verifies that calling malloc in a preinit_array function succeeds, and that
// the resulting pointer can be freed at program termination.
-#include <malloc.h>
#include <stdlib.h>
#include <string.h>
diff --git a/test/scudo/random_shuffle.cpp b/test/scudo/random_shuffle.cpp
index 54768a578..026834034 100644
--- a/test/scudo/random_shuffle.cpp
+++ b/test/scudo/random_shuffle.cpp
@@ -7,6 +7,7 @@
// RUN: %run %t 10000 > %T/random_shuffle_tmp_dir/out2
// RUN: not diff %T/random_shuffle_tmp_dir/out?
// RUN: rm -rf %T/random_shuffle_tmp_dir
+// UNSUPPORTED: i386-linux,i686-linux
// Tests that the allocator shuffles the chunks before returning to the user.
diff --git a/test/scudo/realloc.cpp b/test/scudo/realloc.cpp
index dfad40197..cc4459500 100644
--- a/test/scudo/realloc.cpp
+++ b/test/scudo/realloc.cpp
@@ -20,7 +20,7 @@ int main(int argc, char **argv)
{
void *p, *old_p;
// Those sizes will exercise both allocators (Primary & Secondary).
- std::vector<size_t> sizes{1, 1 << 5, 1 << 10, 1 << 15, 1 << 20};
+ std::vector<size_t> sizes{1, 16, 1024, 32768, 1 << 16, 1 << 17, 1 << 20};
assert(argc == 2);
for (size_t size : sizes) {