aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/tysan/tysan.cpp121
-rw-r--r--compiler-rt/lib/tysan/tysan_platform.h16
-rw-r--r--compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cpp3
-rw-r--r--compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cpp3
-rw-r--r--compiler-rt/test/tysan/basic.c8
-rw-r--r--compiler-rt/test/tysan/simple_verify_outlines.c22
-rw-r--r--compiler-rt/test/tysan/struct-offset-outline.c32
7 files changed, 194 insertions, 11 deletions
diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index 4fa8166..1c67ade 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -22,6 +22,7 @@
#include "tysan/tysan.h"
+#include <stdint.h>
#include <string.h>
using namespace __sanitizer;
@@ -254,10 +255,68 @@ static void reportError(void *Addr, int Size, tysan_type_descriptor *TD,
}
}
+ALWAYS_INLINE
+static void SetShadowType(tysan_type_descriptor *td,
+ tysan_type_descriptor **shadowData,
+ uint64_t AccessSize) {
+ *shadowData = td;
+ uint64_t shadowDataInt = (uint64_t)shadowData;
+
+ for (uint64_t i = 1; i < AccessSize; ++i) {
+ int64_t dataOffset = i << PtrShift();
+ int64_t *badShadowData = (int64_t *)(shadowDataInt + dataOffset);
+ int64_t badTD = int64_t(i) * -1;
+ *badShadowData = badTD;
+ }
+}
+
+ALWAYS_INLINE
+static bool GetNotAllBadTD(uint64_t ShadowDataInt, uint64_t AccessSize) {
+ bool notAllBadTD = false;
+ for (uint64_t i = 1; i < AccessSize; ++i) {
+ int64_t **unkShadowData = (int64_t **)(ShadowDataInt + (i << PtrShift()));
+ int64_t *ILdTD = *unkShadowData;
+ notAllBadTD = notAllBadTD || (ILdTD != nullptr);
+ }
+ return notAllBadTD;
+}
+
+ALWAYS_INLINE
+static bool GetNotAllUnkTD(uint64_t ShadowDataInt, uint64_t AccessSize) {
+ bool notAllBadTD = false;
+ for (uint64_t i = 1; i < AccessSize; ++i) {
+ int64_t *badShadowData = (int64_t *)(ShadowDataInt + (i << PtrShift()));
+ int64_t ILdTD = *badShadowData;
+ notAllBadTD = notAllBadTD || (ILdTD >= 0);
+ }
+ return notAllBadTD;
+}
+
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
-__tysan_check(void *addr, int size, tysan_type_descriptor *td, int flags) {
- GET_CALLER_PC_BP_SP;
+__tysan_instrument_mem_inst(char *dest, char *src, uint64_t size,
+ bool needsMemMove) {
+ tysan_type_descriptor **destShadowDataPtr = shadow_for(dest);
+
+ if (!src) {
+ internal_memset((char *)destShadowDataPtr, 0, size << PtrShift());
+ return;
+ }
+
+ uint64_t srcInt = (uint64_t)src;
+ uint64_t srcShadowInt = ((srcInt & AppMask()) << PtrShift()) + ShadowAddr();
+ uint64_t *srcShadow = (uint64_t *)srcShadowInt;
+ if (needsMemMove) {
+ internal_memmove((char *)destShadowDataPtr, srcShadow, size << PtrShift());
+ } else {
+ internal_memcpy((char *)destShadowDataPtr, srcShadow, size << PtrShift());
+ }
+}
+
+ALWAYS_INLINE
+static void __tysan_check_internal(void *addr, int size,
+ tysan_type_descriptor *td, int flags,
+ uptr pc, uptr bp, uptr sp) {
bool IsRead = flags & 1;
bool IsWrite = flags & 2;
const char *AccessStr;
@@ -300,6 +359,64 @@ __tysan_check(void *addr, int size, tysan_type_descriptor *td, int flags) {
}
}
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__tysan_check(void *addr, int size, tysan_type_descriptor *td, int flags) {
+ GET_CALLER_PC_BP_SP;
+ __tysan_check_internal(addr, size, td, flags, pc, bp, sp);
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__tysan_instrument_with_shadow_update(void *ptr, tysan_type_descriptor *td,
+ bool sanitizeFunction,
+ uint64_t accessSize, int flags) {
+ tysan_type_descriptor **shadowData = shadow_for(ptr);
+ tysan_type_descriptor *loadedTD = *shadowData;
+ bool shadowIsNull = loadedTD == nullptr;
+
+ // TODO, sanitizeFunction is known at compile time, so maybe this is split
+ // into two different functions
+ if (sanitizeFunction) {
+
+ if (td != loadedTD) {
+
+ // We now know that the types did not match (we're on the slow path). If
+ // the type is unknown, then set it.
+ if (shadowIsNull) {
+ // We're about to set the type. Make sure that all bytes in the value
+ // are also of unknown type.
+ bool isAllUnknownTD = GetNotAllUnkTD((uint64_t)shadowData, accessSize);
+ if (isAllUnknownTD) {
+ GET_CALLER_PC_BP_SP;
+ __tysan_check_internal(ptr, accessSize, td, flags, pc, bp, sp);
+ }
+ SetShadowType(td, shadowData, accessSize);
+ } else {
+ GET_CALLER_PC_BP_SP;
+ __tysan_check_internal(ptr, accessSize, td, flags, pc, bp, sp);
+ }
+ } else {
+ // We appear to have the right type. Make sure that all other bytes in
+ // the type are still marked as interior bytes. If not, call the runtime.
+ bool isNotAllBadTD = GetNotAllBadTD((uint64_t)shadowData, accessSize);
+ if (isNotAllBadTD) {
+ GET_CALLER_PC_BP_SP;
+ __tysan_check_internal(ptr, accessSize, td, flags, pc, bp, sp);
+ }
+ }
+ } else if (shadowIsNull) {
+ SetShadowType(td, shadowData, accessSize);
+ }
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
+__tysan_set_shadow_type(void *ptr, tysan_type_descriptor *td,
+ uint64_t accessSize) {
+ // In the mode where writes always set the type, for a write (which does
+ // not also read), we just set the type.
+ tysan_type_descriptor **shadow = shadow_for(ptr);
+ SetShadowType(td, shadow, accessSize);
+}
+
Flags __tysan::flags_data;
SANITIZER_INTERFACE_ATTRIBUTE uptr __tysan_shadow_memory_address;
diff --git a/compiler-rt/lib/tysan/tysan_platform.h b/compiler-rt/lib/tysan/tysan_platform.h
index f013928..19f77f0 100644
--- a/compiler-rt/lib/tysan/tysan_platform.h
+++ b/compiler-rt/lib/tysan/tysan_platform.h
@@ -21,24 +21,28 @@ struct Mapping {
static const uptr kShadowAddr = 0x010000000000ull;
static const uptr kAppAddr = 0x550000000000ull;
static const uptr kAppMemMsk = ~0x780000000000ull;
+ static const uptr kPtrShift = 3;
};
#elif defined(__aarch64__)
struct Mapping39 {
static const uptr kShadowAddr = 0x0800000000ull;
static const uptr kAppAddr = 0x5500000000ull;
static const uptr kAppMemMsk = ~0x7800000000ull;
+ static const uptr kPtrShift = 3;
};
struct Mapping42 {
static const uptr kShadowAddr = 0x10000000000ull;
static const uptr kAppAddr = 0x2aa00000000ull;
static const uptr kAppMemMsk = ~0x3c000000000ull;
+ static const uptr kPtrShift = 3;
};
struct Mapping48 {
static const uptr kShadowAddr = 0x0002000000000ull;
static const uptr kAppAddr = 0x0aaaa00000000ull;
static const uptr kAppMemMsk = ~0x0fff800000000ull;
+ static const uptr kPtrShift = 3;
};
#define TYSAN_RUNTIME_VMA 1
#else
@@ -49,7 +53,12 @@ struct Mapping48 {
extern int vmaSize;
#endif
-enum MappingType { MAPPING_SHADOW_ADDR, MAPPING_APP_ADDR, MAPPING_APP_MASK };
+enum MappingType {
+ MAPPING_SHADOW_ADDR,
+ MAPPING_APP_ADDR,
+ MAPPING_APP_MASK,
+ MAPPING_PTR_SHIFT
+};
template <typename Mapping, int Type> uptr MappingImpl(void) {
switch (Type) {
@@ -59,6 +68,8 @@ template <typename Mapping, int Type> uptr MappingImpl(void) {
return Mapping::kAppAddr;
case MAPPING_APP_MASK:
return Mapping::kAppMemMsk;
+ case MAPPING_PTR_SHIFT:
+ return Mapping::kPtrShift;
}
}
@@ -88,6 +99,9 @@ uptr AppAddr() { return MappingArchImpl<MAPPING_APP_ADDR>(); }
ALWAYS_INLINE
uptr AppMask() { return MappingArchImpl<MAPPING_APP_MASK>(); }
+ALWAYS_INLINE
+uptr PtrShift() { return MappingArchImpl<MAPPING_PTR_SHIFT>(); }
+
} // namespace __tysan
#endif
diff --git a/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cpp b/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cpp
index f12e2b2..651d0c5 100644
--- a/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cpp
+++ b/compiler-rt/test/asan/TestCases/Darwin/suppressions-sandbox.cpp
@@ -15,9 +15,6 @@
// sandbox-exec isn't available on iOS
// UNSUPPORTED: ios
-// Symbolizer fails to find test functions on current macOS bot version
-// XFAIL: system-darwin && target=arm{{.*}}
-
#include <CoreFoundation/CoreFoundation.h>
#if defined(SHARED_LIB)
diff --git a/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cpp b/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cpp
index c7b9280..c062926 100644
--- a/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cpp
+++ b/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cpp
@@ -2,9 +2,6 @@
// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-FWRITE
// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-FREAD
-// Symbolizer fails to find test functions on current macOS bot version
-// XFAIL: system-darwin && target=arm{{.*}}
-
#include <stdio.h>
#include <stdlib.h>
diff --git a/compiler-rt/test/tysan/basic.c b/compiler-rt/test/tysan/basic.c
index 8e66e1a..28b94c4 100644
--- a/compiler-rt/test/tysan/basic.c
+++ b/compiler-rt/test/tysan/basic.c
@@ -1,6 +1,10 @@
-// RUN: %clang_tysan -O0 %s -o %t && %run %t 10 >%t.out.0 2>&1
+// RUN: %clang_tysan -O0 -mllvm -tysan-outline-instrumentation=false %s -o %t && %run %t 10 >%t.out.0 2>&1
// RUN: FileCheck %s < %t.out.0
-// RUN: %clang_tysan -O2 %s -o %t && %run %t 10 >%t.out 2>&1
+// RUN: %clang_tysan -O2 -mllvm -tysan-outline-instrumentation=false %s -o %t && %run %t 10 >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+// RUN: %clang_tysan -O0 -mllvm -tysan-outline-instrumentation=true %s -o %t && %run %t 10 >%t.out.0 2>&1
+// RUN: FileCheck %s < %t.out.0
+// RUN: %clang_tysan -O2 -mllvm -tysan-outline-instrumentation=true %s -o %t && %run %t 10 >%t.out 2>&1
// RUN: FileCheck %s < %t.out
#include <stdio.h>
diff --git a/compiler-rt/test/tysan/simple_verify_outlines.c b/compiler-rt/test/tysan/simple_verify_outlines.c
new file mode 100644
index 0000000..0d0730e
--- /dev/null
+++ b/compiler-rt/test/tysan/simple_verify_outlines.c
@@ -0,0 +1,22 @@
+// RUN: %clang_tysan -mllvm -tysan-outline-instrumentation=true -mllvm -tysan-verify-outlined-instrumentation=true %s -o %t && %run %t >%t.out.0 2>&1
+// RUN: FileCheck %s < %t.out.0
+
+#include <stdio.h>
+
+void printInt(int *i) { printf("%d\n", *i); }
+
+int main() {
+
+ float value = 5.0f;
+ printInt((int *)&value);
+
+ return 0;
+}
+
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK-NEXT: READ of size 4 at {{.*}} with type int accesses an existing object of type float
+// CHECK-NEXT: {{#0 0x.* in printInt}}
+// CHECK-EMPTY:
+// CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK-NEXT: READ of size 4 at {{.*}} with type int accesses an existing object of type float
+// CHECK-NEXT: {{#0 0x.* in printInt}}
diff --git a/compiler-rt/test/tysan/struct-offset-outline.c b/compiler-rt/test/tysan/struct-offset-outline.c
new file mode 100644
index 0000000..c84eb2762
--- /dev/null
+++ b/compiler-rt/test/tysan/struct-offset-outline.c
@@ -0,0 +1,32 @@
+// RUN: %clang_tysan -mllvm -tysan-outline-instrumentation=true -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+// RUN: %clang_tysan -mllvm -tysan-outline-instrumentation=true -mllvm -tysan-verify-outlined-instrumentation=true -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s --check-prefixes='CHECK,CHECK-VERIFY' < %t.out
+
+#include <stdio.h>
+#include <stdlib.h>
+
+struct X {
+ int i;
+ int j;
+};
+
+int foo(struct X *p, struct X *q) {
+ q->j = 1;
+ p->i = 0;
+ // CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+ // CHECK-NEXT: WRITE of size 4 at {{.*}} with type int (in X at offset 0) accesses an existing object of type int (in X at offset 4)
+ // CHECK-NEXT: {{#0 0x.* in foo .*struct-offset-outline.c:}}[[@LINE-3]]
+ // CHECK-VERIFY-EMPTY:
+ // CHECK-VERIFY-NEXT: ERROR: TypeSanitizer: type-aliasing-violation
+ // CHECK-VERIFY-NEXT: WRITE of size 4 at {{.*}} with type int (in X at offset 0) accesses an existing object of type int (in X at offset 4)
+ // CHECK-VERIFY-NEXT: {{#0 0x.* in foo .*struct-offset-outline.c:}}[[@LINE-7]]
+ return q->j;
+}
+
+int main() {
+ unsigned char *p = malloc(3 * sizeof(int));
+ printf("%i\n", foo((struct X *)(p + sizeof(int)), (struct X *)p));
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation