[compiler-rt] [llvm] [TySan] Add initial user facing interfaces (PR #169023)
Matthew Nagy via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 21 03:16:54 PST 2025
https://github.com/gbMattN updated https://github.com/llvm/llvm-project/pull/169023
>From 489197778d233e21d0ca0ae46a8a3dca680a7233 Mon Sep 17 00:00:00 2001
From: gbMattN <matthew.nagy at sony.com>
Date: Thu, 20 Nov 2025 17:23:20 +0000
Subject: [PATCH 1/3] [TySan] add initial user facing interfaces
---
compiler-rt/include/CMakeLists.txt | 1 +
.../include/sanitizer/tysan_interface.h | 42 ++++++++
.../tests/sanitizer_common_test.cpp | 1 +
compiler-rt/lib/tysan/CMakeLists.txt | 2 +
compiler-rt/lib/tysan/tysan.cpp | 36 ++++---
compiler-rt/lib/tysan/tysan.h | 2 +
compiler-rt/lib/tysan/tysan_interface.cpp | 34 +++++++
compiler-rt/lib/tysan/tysan_interface.h | 42 ++++++++
.../test/tysan/interface-manipulate-shadow.c | 99 +++++++++++++++++++
compiler-rt/test/tysan/interface-print-type.c | 33 +++++++
.../gn/secondary/compiler-rt/include/BUILD.gn | 1 +
11 files changed, 281 insertions(+), 12 deletions(-)
create mode 100644 compiler-rt/include/sanitizer/tysan_interface.h
create mode 100644 compiler-rt/lib/tysan/tysan_interface.cpp
create mode 100644 compiler-rt/lib/tysan/tysan_interface.h
create mode 100644 compiler-rt/test/tysan/interface-manipulate-shadow.c
create mode 100644 compiler-rt/test/tysan/interface-print-type.c
diff --git a/compiler-rt/include/CMakeLists.txt b/compiler-rt/include/CMakeLists.txt
index 242d62b9b447b..8443e309d1e95 100644
--- a/compiler-rt/include/CMakeLists.txt
+++ b/compiler-rt/include/CMakeLists.txt
@@ -14,6 +14,7 @@ if (COMPILER_RT_BUILD_SANITIZERS)
sanitizer/scudo_interface.h
sanitizer/tsan_interface.h
sanitizer/tsan_interface_atomic.h
+ sanitizer/tysan_interface.h
sanitizer/ubsan_interface.h
)
set(FUZZER_HEADERS
diff --git a/compiler-rt/include/sanitizer/tysan_interface.h b/compiler-rt/include/sanitizer/tysan_interface.h
new file mode 100644
index 0000000000000..8cb35ae4b5c09
--- /dev/null
+++ b/compiler-rt/include/sanitizer/tysan_interface.h
@@ -0,0 +1,42 @@
+//===-- tsan_interface.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of TypeSanitizer.
+//
+// Public interface header for TySan.
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_TYSAN_INTERFACE_H
+#define SANITIZER_TYSAN_INTERFACE_H
+
+#include <sanitizer/common_interface_defs.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Copies the shadow memory for the source user memory into the shadow memory for the destination user memory
+void SANITIZER_CDECL __tysan_copy_shadow(const void *dst, const void *src, size_t type_size);
+
+// Copies the shadow memory for the source user memory into the shadow memory for each element in the
+// destination array in user memory
+void SANITIZER_CDECL __tysan_copy_shadow_array(const void *dst_array, const void *src, size_t type_size, size_t arraySize);
+
+// Clears the shadow memory for the given range of user memory.
+void SANITIZER_CDECL __tysan_reset_shadow(const void *addr, size_t size);
+
+// Writes the name of the type represented in the shadow memory for the given location in user memory
+// into the given buffer, up to the given size.
+// Returns the length written.
+int SANITIZER_CDECL __tysan_get_type_name(const void *addr, char *buffer, size_t buffer_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
index 111e55ef36bfb..917ba847ad478 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_common_test.cpp
@@ -21,6 +21,7 @@
#include "../../../include/sanitizer/asan_interface.h"
#include "../../../include/sanitizer/msan_interface.h"
#include "../../../include/sanitizer/tsan_interface.h"
+#include "../../../include/sanitizer/tysan_interface.h"
#include "gtest/gtest.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
diff --git a/compiler-rt/lib/tysan/CMakeLists.txt b/compiler-rt/lib/tysan/CMakeLists.txt
index 7d13ae3963919..a878a46322bd2 100644
--- a/compiler-rt/lib/tysan/CMakeLists.txt
+++ b/compiler-rt/lib/tysan/CMakeLists.txt
@@ -4,11 +4,13 @@ include_directories(..)
set(TYSAN_SOURCES
tysan.cpp
tysan_interceptors.cpp
+ tysan_interface.cpp
)
SET(TYSAN_HEADERS
tysan.h
tysan_flags.inc
+ tysan_interface.h
tysan_platform.h
)
diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index 1c67adeba0fc5..fdffe784d0c74 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -56,29 +56,41 @@ static const char *getDisplayName(const char *Name) {
return DName;
}
-static void printTDName(tysan_type_descriptor *td) {
- if (((sptr)td) <= 0) {
- Printf("<unknown type>");
- return;
+int getTDName(void *_td, char *buffer, uptr buffer_size, bool asset_on_error){
+ tysan_type_descriptor* td = (tysan_type_descriptor*)_td;
+ if(((sptr)td) <= 0){
+ return internal_snprintf(buffer, buffer_size, "<unknown type>");
}
+ uptr written = 0;
switch (td->Tag) {
default:
- CHECK(false && "invalid enum value");
+ if (asset_on_error)
+ CHECK(false && "invalid enum value");
+ else
+ written = internal_snprintf(buffer, buffer_size, "<invalid shadow>");
break;
case TYSAN_MEMBER_TD:
- printTDName(td->Member.Access);
- if (td->Member.Access != td->Member.Base) {
- Printf(" (in ");
- printTDName(td->Member.Base);
- Printf(" at offset %zu)", td->Member.Offset);
+ written = getTDName(td->Member.Access, buffer, buffer_size, false);
+ if (td->Member.Access != td->Member.Base && written != buffer_size) {
+ written += internal_snprintf(&buffer[written], buffer_size - written, " (in ");
+ written += getTDName(td->Member.Base, &buffer[written], buffer_size - written, false);
+ written += internal_snprintf(&buffer[written], buffer_size - written, " at offset %zu)", td->Member.Offset);
}
break;
case TYSAN_STRUCT_TD:
- Printf("%s", getDisplayName(
- (char *)(td->Struct.Members + td->Struct.MemberCount)));
+ written = internal_snprintf(buffer, buffer_size, "%s",
+ getDisplayName((char *)(td->Struct.Members + td->Struct.MemberCount)));
break;
}
+ return written;
+}
+
+static void printTDName(tysan_type_descriptor *td) {
+ static const uptr nameBufferSize = 512;
+ static char nameBuffer[nameBufferSize];
+ getTDName(td, nameBuffer, nameBufferSize, true);
+ Printf("%s", nameBuffer);
}
static tysan_type_descriptor *getRootTD(tysan_type_descriptor *TD) {
diff --git a/compiler-rt/lib/tysan/tysan.h b/compiler-rt/lib/tysan/tysan.h
index 97df28037b0d2..b7b1306cf10bd 100644
--- a/compiler-rt/lib/tysan/tysan.h
+++ b/compiler-rt/lib/tysan/tysan.h
@@ -20,11 +20,13 @@ using __sanitizer::sptr;
using __sanitizer::u16;
using __sanitizer::uptr;
+#include "tysan_interface.h"
#include "tysan_platform.h"
extern "C" {
void tysan_set_type_unknown(const void *addr, uptr size);
void tysan_copy_types(const void *daddr, const void *saddr, uptr size);
+int getTDName(void *td, char *buffer, uptr buffer_size, bool assert_on_error);
}
namespace __tysan {
diff --git a/compiler-rt/lib/tysan/tysan_interface.cpp b/compiler-rt/lib/tysan/tysan_interface.cpp
new file mode 100644
index 0000000000000..c2da6246b0044
--- /dev/null
+++ b/compiler-rt/lib/tysan/tysan_interface.cpp
@@ -0,0 +1,34 @@
+//===-- tysan_interface.inc --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of TypeSanitizer.
+//
+//===----------------------------------------------------------------------===//
+#include "tysan.h"
+#include "tysan_interface.h"
+
+void __tysan_copy_shadow(const void *dst, const void *src, size_t type_size){
+ tysan_copy_types(dst, src, type_size);
+}
+
+void __tysan_copy_shadow_array(const void *dst_array, const void *src, size_t type_size, size_t arraySize){
+ const void* dst = dst_array;
+ for(size_t i = 0; i < arraySize; i++){
+ tysan_copy_types(dst, src, type_size);
+ dst = (void*)(((uptr)dst) + type_size);
+ }
+}
+
+void __tysan_reset_shadow(const void *addr, size_t size){
+ tysan_set_type_unknown(addr, size);
+}
+
+int __tysan_get_type_name(const void *addr, char *buffer, size_t buffer_size){
+ void** shadow = (void**)__tysan::shadow_for(addr);
+ return getTDName(*shadow, buffer, buffer_size, false);
+}
diff --git a/compiler-rt/lib/tysan/tysan_interface.h b/compiler-rt/lib/tysan/tysan_interface.h
new file mode 100644
index 0000000000000..5a5e5cc08d2b3
--- /dev/null
+++ b/compiler-rt/lib/tysan/tysan_interface.h
@@ -0,0 +1,42 @@
+//===-- tysan_interface.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of TypeSanitizer.
+//
+// The functions declared in this header will be inserted by the instrumentation
+// module.
+// This header can be included by the instrumented program or by TySan tests.
+//===----------------------------------------------------------------------===//
+
+#ifndef TYSAN_INTERFACE_H
+#define TYSAN_INTERFACE_H
+
+#include <sanitizer_common/sanitizer_internal_defs.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tysan_copy_shadow(const void *dst, const void *src, size_t type_size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tysan_copy_shadow_array(const void *dst_array, const void *src, size_t type_size, size_t arraySize);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __tysan_reset_shadow(const void *addr, size_t size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __tysan_get_type_name(const void *addr, char *buffer, size_t buffer_size);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/compiler-rt/test/tysan/interface-manipulate-shadow.c b/compiler-rt/test/tysan/interface-manipulate-shadow.c
new file mode 100644
index 0000000000000..504de2876cf26
--- /dev/null
+++ b/compiler-rt/test/tysan/interface-manipulate-shadow.c
@@ -0,0 +1,99 @@
+// REQUIRES: system-linux || system-darwin
+// RUN: %clang_tysan %s -g -shared -fpic -o %t.so -DBUILD_SO
+// RUN: %clang_tysan %s -g -o %t
+// RUN: %run %t %t.so 2>&1 | FileCheck %s
+
+// Compilers can't optimize using type aliasing across the bounds of dynamic librarys
+// When passing memory between instrumented executables and dlls, you may want to alter TySan's
+// shadow to prevent it from catching technically correct, yet harmless aliasing violations
+
+#ifdef BUILD_SO
+float useFloatArray(float* mem){
+ mem[0] = 2.f;
+ mem[1] = 3.f;
+ return mem[0] + mem[1];
+}
+
+int useIntArray(int* mem){
+ mem[0] = 2;
+ mem[1] = 3;
+ mem[2] = 5;
+ return mem[0] + mem[1] + mem[2];
+}
+#else
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <sanitizer/tysan_interface.h>
+#include <stdio.h>
+
+typedef float(*lib_func1_t)(float*);
+typedef int(*lib_func2_t)(int*);
+
+void print_flush(const char* message){
+ printf("%s\n", message);
+ fflush(stdout);
+}
+
+int main(int argc, char* argv[]){
+ assert(argc >=2);
+ void *libHandle = dlopen(argv[1], RTLD_LAZY);
+ assert(libHandle);
+
+ lib_func1_t useFloatArray = (lib_func1_t)dlsym(libHandle, "useFloatArray");
+ lib_func2_t useIntArray = (lib_func2_t)dlsym(libHandle, "useIntArray");
+
+ char memory[sizeof(int) * 3];
+ int iResult = 0;
+ float fResult = 0.f;
+ print_flush("Calling with omnipotent char memory");
+ fResult = useFloatArray((float*)memory);
+ print_flush("Shadow now has floats in");
+ iResult = useIntArray((int*)memory);
+
+// CHECK: Calling with omnipotent char memory
+// CHECK-NEXT: Shadow now has floats in
+// CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
+// CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type int accesses an existing object of type float
+
+ __tysan_reset_shadow(memory, sizeof(memory));
+ print_flush("Shadow has been reset");
+ useIntArray((int*)memory);
+ print_flush("Completed int array");
+
+// CHECK: Shadow has been reset
+// CHECK-NEXT: Completed int array
+
+ // Set shadow type to float
+ __tysan_copy_shadow_array(memory, &fResult, sizeof(float), 3);
+ print_flush("Float array with float set shadow");
+ useFloatArray((float*)memory);
+ print_flush("Int array with float set shadow");
+ useIntArray((int*)memory);
+
+// CHECK: Float array with float set shadow
+// CHECK-NEXT: Int array with float set shadow
+// CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
+// CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type int accesses an existing object of type float
+
+ // Set shadow type to int
+ for(size_t i = 0; i < 3; i++){
+ __tysan_copy_shadow(&memory[sizeof(int) * i], &iResult, sizeof(int));
+ }
+ print_flush("Float array with int set shadow");
+ useFloatArray((float*)memory);
+ print_flush("Int array with int set shadow");
+ useIntArray((int*)memory);
+ print_flush("Completed int array");
+
+// CHECK: Float array with int set shadow
+// CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
+// CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type float accesses an existing object of type int
+// CHECK: Int array with int set shadow
+// CHECK-NEXT: Completed int array
+
+ dlclose(libHandle);
+ return 0;
+}
+
+#endif
diff --git a/compiler-rt/test/tysan/interface-print-type.c b/compiler-rt/test/tysan/interface-print-type.c
new file mode 100644
index 0000000000000..c61a7dc477353
--- /dev/null
+++ b/compiler-rt/test/tysan/interface-print-type.c
@@ -0,0 +1,33 @@
+// RUN: %clang_tysan %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <sanitizer/tysan_interface.h>
+#include <stdio.h>
+
+struct S{
+ int i;
+ float f;
+};
+
+void printInt(int* i){
+ const int bufferSize = 512;
+ static char nameBuffer[bufferSize];
+ __tysan_get_type_name(i, nameBuffer, 512);
+ printf("%d, %s\n", *i, nameBuffer);
+ fflush(stdout);
+}
+
+int main(){
+ struct S s;
+ s.i = 4;
+ printInt((int*)&s);
+// CHECK: 4, int (in S at offset 0)
+
+ s.f = 5.0f;
+// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: READ of size 4 at 0x{{.*}} with type int accesses an existing object of type float (in S at offset 4)
+// CHECK: {{.*}}, float (in S at offset 4)
+ printInt((int*)&s.f);
+
+ return 0;
+}
diff --git a/llvm/utils/gn/secondary/compiler-rt/include/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/include/BUILD.gn
index 273fd7172da62..8e8ce837ef21e 100644
--- a/llvm/utils/gn/secondary/compiler-rt/include/BUILD.gn
+++ b/llvm/utils/gn/secondary/compiler-rt/include/BUILD.gn
@@ -22,6 +22,7 @@ copy("include") {
"sanitizer/scudo_interface.h",
"sanitizer/tsan_interface.h",
"sanitizer/tsan_interface_atomic.h",
+ sanitizer/tysan_interface.h
"sanitizer/ubsan_interface.h",
]
outputs = [ "$clang_resource_dir/include/{{source_target_relative}}" ]
>From 8123f51ee4c0afb26cc1ef0bc67ffd8b02557f42 Mon Sep 17 00:00:00 2001
From: gbMattN <matthew.nagy at sony.com>
Date: Fri, 21 Nov 2025 11:15:52 +0000
Subject: [PATCH 2/3] format
---
.../include/sanitizer/tsan_interface.h | 2 +-
.../include/sanitizer/tysan_interface.h | 26 +--
compiler-rt/lib/tysan/tysan.cpp | 14 +-
compiler-rt/lib/tysan/tysan_interface.cpp | 31 ++--
compiler-rt/lib/tysan/tysan_interface.h | 7 +-
.../test/tysan/interface-manipulate-shadow.c | 154 +++++++++---------
compiler-rt/test/tysan/interface-print-type.c | 40 ++---
7 files changed, 143 insertions(+), 131 deletions(-)
diff --git a/compiler-rt/include/sanitizer/tsan_interface.h b/compiler-rt/include/sanitizer/tsan_interface.h
index e11a4175cd8ed..98fac85fd907a 100644
--- a/compiler-rt/include/sanitizer/tsan_interface.h
+++ b/compiler-rt/include/sanitizer/tsan_interface.h
@@ -1,4 +1,4 @@
-//===-- tsan_interface.h ----------------------------------------*- C++ -*-===//
+//===-- tysan_interface.h ---------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/compiler-rt/include/sanitizer/tysan_interface.h b/compiler-rt/include/sanitizer/tysan_interface.h
index 8cb35ae4b5c09..d198363df3a34 100644
--- a/compiler-rt/include/sanitizer/tysan_interface.h
+++ b/compiler-rt/include/sanitizer/tysan_interface.h
@@ -1,4 +1,4 @@
-//===-- tsan_interface.h ----------------------------------------*- C++ -*-===//
+//===-- tysan_interface.h ---------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -20,20 +20,26 @@
extern "C" {
#endif
-// Copies the shadow memory for the source user memory into the shadow memory for the destination user memory
-void SANITIZER_CDECL __tysan_copy_shadow(const void *dst, const void *src, size_t type_size);
+// Copies the shadow memory for the source user memory into the shadow memory
+// for the destination user memory
+void SANITIZER_CDECL __tysan_copy_shadow(const void *dst, const void *src,
+ size_t type_size);
-// Copies the shadow memory for the source user memory into the shadow memory for each element in the
-// destination array in user memory
-void SANITIZER_CDECL __tysan_copy_shadow_array(const void *dst_array, const void *src, size_t type_size, size_t arraySize);
+// Copies the shadow memory for the source user memory into the shadow memory
+// for each element in the destination array in user memory
+void SANITIZER_CDECL __tysan_copy_shadow_array(const void *dst_array,
+ const void *src,
+ size_t type_size,
+ size_t arraySize);
// Clears the shadow memory for the given range of user memory.
void SANITIZER_CDECL __tysan_reset_shadow(const void *addr, size_t size);
-// Writes the name of the type represented in the shadow memory for the given location in user memory
-// into the given buffer, up to the given size.
-// Returns the length written.
-int SANITIZER_CDECL __tysan_get_type_name(const void *addr, char *buffer, size_t buffer_size);
+// Writes the name of the type represented in the shadow memory for the given
+// location in user memory into the given buffer, up to the given size. Returns
+// the length written.
+int SANITIZER_CDECL __tysan_get_type_name(const void *addr, char *buffer,
+ size_t buffer_size);
#ifdef __cplusplus
}
diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index fdffe784d0c74..b234dbf272c6e 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -73,14 +73,18 @@ int getTDName(void *_td, char *buffer, uptr buffer_size, bool asset_on_error){
case TYSAN_MEMBER_TD:
written = getTDName(td->Member.Access, buffer, buffer_size, false);
if (td->Member.Access != td->Member.Base && written != buffer_size) {
- written += internal_snprintf(&buffer[written], buffer_size - written, " (in ");
- written += getTDName(td->Member.Base, &buffer[written], buffer_size - written, false);
- written += internal_snprintf(&buffer[written], buffer_size - written, " at offset %zu)", td->Member.Offset);
+ written +=
+ internal_snprintf(&buffer[written], buffer_size - written, " (in ");
+ written += getTDName(td->Member.Base, &buffer[written],
+ buffer_size - written, false);
+ written += internal_snprintf(&buffer[written], buffer_size - written,
+ " at offset %zu)", td->Member.Offset);
}
break;
case TYSAN_STRUCT_TD:
- written = internal_snprintf(buffer, buffer_size, "%s",
- getDisplayName((char *)(td->Struct.Members + td->Struct.MemberCount)));
+ written = internal_snprintf(
+ buffer, buffer_size, "%s",
+ getDisplayName((char *)(td->Struct.Members + td->Struct.MemberCount)));
break;
}
return written;
diff --git a/compiler-rt/lib/tysan/tysan_interface.cpp b/compiler-rt/lib/tysan/tysan_interface.cpp
index c2da6246b0044..3d7d9d101c5f9 100644
--- a/compiler-rt/lib/tysan/tysan_interface.cpp
+++ b/compiler-rt/lib/tysan/tysan_interface.cpp
@@ -1,4 +1,4 @@
-//===-- tysan_interface.inc --------------------------------------*- C++ -*-===//
+//===-- tysan_interface.cpp -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -9,26 +9,27 @@
// This file is a part of TypeSanitizer.
//
//===----------------------------------------------------------------------===//
-#include "tysan.h"
#include "tysan_interface.h"
+#include "tysan.h"
-void __tysan_copy_shadow(const void *dst, const void *src, size_t type_size){
- tysan_copy_types(dst, src, type_size);
+void __tysan_copy_shadow(const void *dst, const void *src, size_t type_size) {
+ tysan_copy_types(dst, src, type_size);
}
-void __tysan_copy_shadow_array(const void *dst_array, const void *src, size_t type_size, size_t arraySize){
- const void* dst = dst_array;
- for(size_t i = 0; i < arraySize; i++){
- tysan_copy_types(dst, src, type_size);
- dst = (void*)(((uptr)dst) + type_size);
- }
+void __tysan_copy_shadow_array(const void *dst_array, const void *src,
+ size_t type_size, size_t arraySize) {
+ const void *dst = dst_array;
+ for (size_t i = 0; i < arraySize; i++) {
+ tysan_copy_types(dst, src, type_size);
+ dst = (void *)(((uptr)dst) + type_size);
+ }
}
-void __tysan_reset_shadow(const void *addr, size_t size){
- tysan_set_type_unknown(addr, size);
+void __tysan_reset_shadow(const void *addr, size_t size) {
+ tysan_set_type_unknown(addr, size);
}
-int __tysan_get_type_name(const void *addr, char *buffer, size_t buffer_size){
- void** shadow = (void**)__tysan::shadow_for(addr);
- return getTDName(*shadow, buffer, buffer_size, false);
+int __tysan_get_type_name(const void *addr, char *buffer, size_t buffer_size) {
+ void **shadow = (void **)__tysan::shadow_for(addr);
+ return getTDName(*shadow, buffer, buffer_size, false);
}
diff --git a/compiler-rt/lib/tysan/tysan_interface.h b/compiler-rt/lib/tysan/tysan_interface.h
index 5a5e5cc08d2b3..9af0c66f0b606 100644
--- a/compiler-rt/lib/tysan/tysan_interface.h
+++ b/compiler-rt/lib/tysan/tysan_interface.h
@@ -1,4 +1,4 @@
-//===-- tysan_interface.h ----------------------------------------*- C++ -*-===//
+//===-- tysan_interface.h ---------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -27,7 +27,8 @@ SANITIZER_INTERFACE_ATTRIBUTE
void __tysan_copy_shadow(const void *dst, const void *src, size_t type_size);
SANITIZER_INTERFACE_ATTRIBUTE
-void __tysan_copy_shadow_array(const void *dst_array, const void *src, size_t type_size, size_t arraySize);
+void __tysan_copy_shadow_array(const void *dst_array, const void *src,
+ size_t type_size, size_t arraySize);
SANITIZER_INTERFACE_ATTRIBUTE
void __tysan_reset_shadow(const void *addr, size_t size);
@@ -36,7 +37,7 @@ SANITIZER_INTERFACE_ATTRIBUTE
int __tysan_get_type_name(const void *addr, char *buffer, size_t buffer_size);
#ifdef __cplusplus
-} // extern "C"
+} // extern "C"
#endif
#endif
diff --git a/compiler-rt/test/tysan/interface-manipulate-shadow.c b/compiler-rt/test/tysan/interface-manipulate-shadow.c
index 504de2876cf26..25614e25e1f6c 100644
--- a/compiler-rt/test/tysan/interface-manipulate-shadow.c
+++ b/compiler-rt/test/tysan/interface-manipulate-shadow.c
@@ -8,92 +8,92 @@
// shadow to prevent it from catching technically correct, yet harmless aliasing violations
#ifdef BUILD_SO
-float useFloatArray(float* mem){
- mem[0] = 2.f;
- mem[1] = 3.f;
- return mem[0] + mem[1];
+float useFloatArray(float *mem) {
+ mem[0] = 2.f;
+ mem[1] = 3.f;
+ return mem[0] + mem[1];
}
-int useIntArray(int* mem){
- mem[0] = 2;
- mem[1] = 3;
- mem[2] = 5;
- return mem[0] + mem[1] + mem[2];
+int useIntArray(int *mem) {
+ mem[0] = 2;
+ mem[1] = 3;
+ mem[2] = 5;
+ return mem[0] + mem[1] + mem[2];
}
#else
-#include <assert.h>
-#include <dlfcn.h>
-#include <sanitizer/tysan_interface.h>
-#include <stdio.h>
+# include <assert.h>
+# include <dlfcn.h>
+# include <sanitizer/tysan_interface.h>
+# include <stdio.h>
-typedef float(*lib_func1_t)(float*);
-typedef int(*lib_func2_t)(int*);
+typedef float (*lib_func1_t)(float *);
+typedef int (*lib_func2_t)(int *);
-void print_flush(const char* message){
- printf("%s\n", message);
- fflush(stdout);
+void print_flush(const char *message) {
+ printf("%s\n", message);
+ fflush(stdout);
}
-int main(int argc, char* argv[]){
- assert(argc >=2);
- void *libHandle = dlopen(argv[1], RTLD_LAZY);
- assert(libHandle);
-
- lib_func1_t useFloatArray = (lib_func1_t)dlsym(libHandle, "useFloatArray");
- lib_func2_t useIntArray = (lib_func2_t)dlsym(libHandle, "useIntArray");
-
- char memory[sizeof(int) * 3];
- int iResult = 0;
- float fResult = 0.f;
- print_flush("Calling with omnipotent char memory");
- fResult = useFloatArray((float*)memory);
- print_flush("Shadow now has floats in");
- iResult = useIntArray((int*)memory);
-
-// CHECK: Calling with omnipotent char memory
-// CHECK-NEXT: Shadow now has floats in
-// CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
-// CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type int accesses an existing object of type float
-
- __tysan_reset_shadow(memory, sizeof(memory));
- print_flush("Shadow has been reset");
- useIntArray((int*)memory);
- print_flush("Completed int array");
-
-// CHECK: Shadow has been reset
-// CHECK-NEXT: Completed int array
-
- // Set shadow type to float
- __tysan_copy_shadow_array(memory, &fResult, sizeof(float), 3);
- print_flush("Float array with float set shadow");
- useFloatArray((float*)memory);
- print_flush("Int array with float set shadow");
- useIntArray((int*)memory);
-
-// CHECK: Float array with float set shadow
-// CHECK-NEXT: Int array with float set shadow
-// CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
-// CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type int accesses an existing object of type float
-
- // Set shadow type to int
- for(size_t i = 0; i < 3; i++){
- __tysan_copy_shadow(&memory[sizeof(int) * i], &iResult, sizeof(int));
- }
- print_flush("Float array with int set shadow");
- useFloatArray((float*)memory);
- print_flush("Int array with int set shadow");
- useIntArray((int*)memory);
- print_flush("Completed int array");
-
-// CHECK: Float array with int set shadow
-// CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
-// CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type float accesses an existing object of type int
-// CHECK: Int array with int set shadow
-// CHECK-NEXT: Completed int array
-
- dlclose(libHandle);
- return 0;
+int main(int argc, char *argv[]) {
+ assert(argc >= 2);
+ void *libHandle = dlopen(argv[1], RTLD_LAZY);
+ assert(libHandle);
+
+ lib_func1_t useFloatArray = (lib_func1_t)dlsym(libHandle, "useFloatArray");
+ lib_func2_t useIntArray = (lib_func2_t)dlsym(libHandle, "useIntArray");
+
+ char memory[sizeof(int) * 3];
+ int iResult = 0;
+ float fResult = 0.f;
+ print_flush("Calling with omnipotent char memory");
+ fResult = useFloatArray((float *)memory);
+ print_flush("Shadow now has floats in");
+ iResult = useIntArray((int *)memory);
+
+ // CHECK: Calling with omnipotent char memory
+ // CHECK-NEXT: Shadow now has floats in
+ // CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
+ // CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type int accesses an existing object of type float
+
+ __tysan_reset_shadow(memory, sizeof(memory));
+ print_flush("Shadow has been reset");
+ useIntArray((int *)memory);
+ print_flush("Completed int array");
+
+ // CHECK: Shadow has been reset
+ // CHECK-NEXT: Completed int array
+
+ // Set shadow type to float
+ __tysan_copy_shadow_array(memory, &fResult, sizeof(float), 3);
+ print_flush("Float array with float set shadow");
+ useFloatArray((float *)memory);
+ print_flush("Int array with float set shadow");
+ useIntArray((int *)memory);
+
+ // CHECK: Float array with float set shadow
+ // CHECK-NEXT: Int array with float set shadow
+ // CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
+ // CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type int accesses an existing object of type float
+
+ // Set shadow type to int
+ for (size_t i = 0; i < 3; i++) {
+ __tysan_copy_shadow(&memory[sizeof(int) * i], &iResult, sizeof(int));
+ }
+ print_flush("Float array with int set shadow");
+ useFloatArray((float *)memory);
+ print_flush("Int array with int set shadow");
+ useIntArray((int *)memory);
+ print_flush("Completed int array");
+
+ // CHECK: Float array with int set shadow
+ // CHECK-NEXT: ERROR: TypeSanitizer: type-aliasing-violation on address
+ // CHECK-NEXT: WRITE of size 4 at 0x{{.*}} with type float accesses an existing object of type int
+ // CHECK: Int array with int set shadow
+ // CHECK-NEXT: Completed int array
+
+ dlclose(libHandle);
+ return 0;
}
#endif
diff --git a/compiler-rt/test/tysan/interface-print-type.c b/compiler-rt/test/tysan/interface-print-type.c
index c61a7dc477353..18c3bb0ceab20 100644
--- a/compiler-rt/test/tysan/interface-print-type.c
+++ b/compiler-rt/test/tysan/interface-print-type.c
@@ -4,30 +4,30 @@
#include <sanitizer/tysan_interface.h>
#include <stdio.h>
-struct S{
- int i;
- float f;
+struct S {
+ int i;
+ float f;
};
-void printInt(int* i){
- const int bufferSize = 512;
- static char nameBuffer[bufferSize];
- __tysan_get_type_name(i, nameBuffer, 512);
- printf("%d, %s\n", *i, nameBuffer);
- fflush(stdout);
+void printInt(int *i) {
+ const int bufferSize = 512;
+ static char nameBuffer[bufferSize];
+ __tysan_get_type_name(i, nameBuffer, 512);
+ printf("%d, %s\n", *i, nameBuffer);
+ fflush(stdout);
}
-int main(){
- struct S s;
- s.i = 4;
- printInt((int*)&s);
-// CHECK: 4, int (in S at offset 0)
+int main() {
+ struct S s;
+ s.i = 4;
+ printInt((int *)&s);
+ // CHECK: 4, int (in S at offset 0)
- s.f = 5.0f;
-// CHECK: ERROR: TypeSanitizer: type-aliasing-violation
-// CHECK: READ of size 4 at 0x{{.*}} with type int accesses an existing object of type float (in S at offset 4)
-// CHECK: {{.*}}, float (in S at offset 4)
- printInt((int*)&s.f);
+ s.f = 5.0f;
+ // CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+ // CHECK: READ of size 4 at 0x{{.*}} with type int accesses an existing object of type float (in S at offset 4)
+ // CHECK: {{.*}}, float (in S at offset 4)
+ printInt((int *)&s.f);
- return 0;
+ return 0;
}
>From 26c481fbbd8fe9a803f2822bda743d90cd23dea5 Mon Sep 17 00:00:00 2001
From: gbMattN <matthew.nagy at sony.com>
Date: Fri, 21 Nov 2025 11:16:44 +0000
Subject: [PATCH 3/3] remove typo
---
compiler-rt/include/sanitizer/tsan_interface.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/compiler-rt/include/sanitizer/tsan_interface.h b/compiler-rt/include/sanitizer/tsan_interface.h
index 98fac85fd907a..e11a4175cd8ed 100644
--- a/compiler-rt/include/sanitizer/tsan_interface.h
+++ b/compiler-rt/include/sanitizer/tsan_interface.h
@@ -1,4 +1,4 @@
-//===-- tysan_interface.h ---------------------------------------*- C++ -*-===//
+//===-- tsan_interface.h ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
More information about the llvm-commits
mailing list