From 489197778d233e21d0ca0ae46a8a3dca680a7233 Mon Sep 17 00:00:00 2001 From: gbMattN Date: Thu, 20 Nov 2025 17:23:20 +0000 Subject: [PATCH 1/4] [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 +#include + +#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(""); - 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, ""); } + 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, ""); 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 +#include + +#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 +#include +#include +#include + +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 +#include + +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 Date: Fri, 21 Nov 2025 11:15:52 +0000 Subject: [PATCH 2/4] 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 -#include -#include -#include +# include +# include +# include +# include -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 #include -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 Date: Fri, 21 Nov 2025 11:16:44 +0000 Subject: [PATCH 3/4] 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. From 4e6c0628a03bd81c87e5df7d5ade040790eeb281 Mon Sep 17 00:00:00 2001 From: gbMattN Date: Fri, 21 Nov 2025 11:20:37 +0000 Subject: [PATCH 4/4] format --- compiler-rt/lib/tysan/tysan.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp index b234dbf272c6e..4a9f563ee43df 100644 --- a/compiler-rt/lib/tysan/tysan.cpp +++ b/compiler-rt/lib/tysan/tysan.cpp @@ -56,16 +56,16 @@ static const char *getDisplayName(const char *Name) { return DName; } -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){ +int getTDName(void *_td, char *buffer, uptr buffer_size, bool assert_on_error) { + tysan_type_descriptor *td = (tysan_type_descriptor *)_td; + if (((sptr)td) <= 0) { return internal_snprintf(buffer, buffer_size, ""); } uptr written = 0; switch (td->Tag) { default: - if (asset_on_error) + if (assert_on_error) CHECK(false && "invalid enum value"); else written = internal_snprintf(buffer, buffer_size, "");