Skip to content

Commit c135f6f

Browse files
authored
[TySan] Add initial Type Sanitizer support to Clang) (#76260)
This patch introduces the Clang components of type sanitizer: a sanitizer for type-based aliasing violations. It is based on Hal Finkel's https://reviews.llvm.org/D32198. The Clang changes are mostly formulaic, the one specific change being that when the TBAA sanitizer is enabled, TBAA is always generated, even at -O0. It goes together with the corresponding LLVM changes (#76259) and compiler-rt changes (#76261) PR: #76260
1 parent cf4375d commit c135f6f

File tree

16 files changed

+183
-13
lines changed

16 files changed

+183
-13
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,10 @@ Sanitizers
11761176
<https://clang.llvm.org/docs/SanitizerSpecialCaseList.html>`_. See that link
11771177
for examples.
11781178

1179+
- Introduced an experimental Type Sanitizer, activated by using the
1180+
``-fsanitize=type`` flag. This sanitizer detects violations of C/C++ type-based
1181+
aliasing rules.
1182+
11791183
Python Binding Changes
11801184
----------------------
11811185
- Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.

clang/include/clang/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ FEATURE(numerical_stability_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Nume
102102
FEATURE(memory_sanitizer,
103103
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
104104
SanitizerKind::KernelMemory))
105+
FEATURE(type_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Type))
105106
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
106107
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
107108
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))

clang/include/clang/Basic/Sanitizers.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ SANITIZER("fuzzer", Fuzzer)
7373
// libFuzzer-required instrumentation, no linking.
7474
SANITIZER("fuzzer-no-link", FuzzerNoLink)
7575

76+
// TypeSanitizer
77+
SANITIZER("type", Type)
78+
7679
// ThreadSanitizer
7780
SANITIZER("thread", Thread)
7881

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class SanitizerArgs {
8787
bool needsHwasanAliasesRt() const {
8888
return needsHwasanRt() && HwasanUseAliases;
8989
}
90+
bool needsTysanRt() const { return Sanitizers.has(SanitizerKind::Type); }
9091
bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); }
9192
bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); }
9293
bool needsFuzzer() const { return Sanitizers.has(SanitizerKind::Fuzzer); }

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
7878
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
7979
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
80+
#include "llvm/Transforms/Instrumentation/TypeSanitizer.h"
8081
#include "llvm/Transforms/ObjCARC.h"
8182
#include "llvm/Transforms/Scalar/EarlyCSE.h"
8283
#include "llvm/Transforms/Scalar/GVN.h"
@@ -735,6 +736,11 @@ static void addSanitizers(const Triple &TargetTriple,
735736
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
736737
}
737738

739+
if (LangOpts.Sanitize.has(SanitizerKind::Type)) {
740+
MPM.addPass(ModuleTypeSanitizerPass());
741+
MPM.addPass(createModuleToFunctionPassAdaptor(TypeSanitizerPass()));
742+
}
743+
738744
if (LangOpts.Sanitize.has(SanitizerKind::NumericalStability))
739745
MPM.addPass(NumericalStabilitySanitizerPass());
740746

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
479479
!isInNoSanitizeList(SanitizerKind::MemtagStack, Fn, Loc))
480480
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
481481

482+
if (getLangOpts().Sanitize.has(SanitizerKind::Type) &&
483+
!isInNoSanitizeList(SanitizerKind::Type, Fn, Loc))
484+
Fn->addFnAttr(llvm::Attribute::SanitizeType);
485+
482486
if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&
483487
!isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
484488
Fn->addFnAttr(llvm::Attribute::SanitizeThread);

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
837837
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
838838
if (SanOpts.has(SanitizerKind::Thread))
839839
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
840+
if (SanOpts.has(SanitizerKind::Type))
841+
Fn->addFnAttr(llvm::Attribute::SanitizeType);
840842
if (SanOpts.has(SanitizerKind::NumericalStability))
841843
Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
842844
if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,8 @@ CodeGenModule::CodeGenModule(ASTContext &C,
397397
if (LangOpts.HLSL)
398398
createHLSLRuntime();
399399

400-
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
401-
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
400+
// Enable TBAA unless it's suppressed. TSan and TySan need TBAA even at O0.
401+
if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Thread | SanitizerKind::Type) ||
402402
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
403403
TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts,
404404
getLangOpts()));

clang/lib/CodeGen/CodeGenTBAA.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
314314
}
315315

316316
llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
317-
// At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
318-
if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
317+
// At -O0 or relaxed aliasing, TBAA is not emitted for regular types (unless
318+
// we're running TypeSanitizer).
319+
if (!Features.Sanitize.has(SanitizerKind::Type) &&
320+
(CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing))
319321
return nullptr;
320322

321323
// If the type has the may_alias attribute (even on a typedef), it is

clang/lib/CodeGen/SanitizerMetadata.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ using namespace CodeGen;
1919

2020
SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {}
2121

22-
static bool isAsanHwasanOrMemTag(const SanitizerSet &SS) {
22+
static bool isAsanHwasanMemTagOrTysan(const SanitizerSet &SS) {
2323
return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress |
24-
SanitizerKind::HWAddress | SanitizerKind::MemTag);
24+
SanitizerKind::HWAddress | SanitizerKind::MemTag |
25+
SanitizerKind::Type);
2526
}
2627

2728
static SanitizerMask expandKernelSanitizerMasks(SanitizerMask Mask) {
@@ -68,7 +69,7 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
6869
SanitizerMask NoSanitizeAttrMask,
6970
bool IsDynInit) {
7071
SanitizerSet FsanitizeArgument = CGM.getLangOpts().Sanitize;
71-
if (!isAsanHwasanOrMemTag(FsanitizeArgument))
72+
if (!isAsanHwasanMemTagOrTysan(FsanitizeArgument))
7273
return;
7374

7475
FsanitizeArgument.Mask = expandKernelSanitizerMasks(FsanitizeArgument.Mask);
@@ -105,11 +106,32 @@ void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV,
105106
GV, Loc, Ty, "init");
106107

107108
GV->setSanitizerMetadata(Meta);
109+
110+
if (Ty.isNull() || !CGM.getLangOpts().Sanitize.has(SanitizerKind::Type) ||
111+
NoSanitizeAttrMask & SanitizerKind::Type)
112+
return;
113+
114+
llvm::MDNode *TBAAInfo = CGM.getTBAATypeInfo(Ty);
115+
if (!TBAAInfo || TBAAInfo == CGM.getTBAATypeInfo(CGM.getContext().CharTy))
116+
return;
117+
118+
llvm::Metadata *GlobalMetadata[] = {llvm::ConstantAsMetadata::get(GV),
119+
TBAAInfo};
120+
121+
// Metadata for the global already registered.
122+
if (llvm::MDNode::getIfExists(CGM.getLLVMContext(), GlobalMetadata))
123+
return;
124+
125+
llvm::MDNode *ThisGlobal =
126+
llvm::MDNode::get(CGM.getLLVMContext(), GlobalMetadata);
127+
llvm::NamedMDNode *TysanGlobals =
128+
CGM.getModule().getOrInsertNamedMetadata("llvm.tysan.globals");
129+
TysanGlobals->addOperand(ThisGlobal);
108130
}
109131

110132
void SanitizerMetadata::reportGlobal(llvm::GlobalVariable *GV, const VarDecl &D,
111133
bool IsDynInit) {
112-
if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
134+
if (!isAsanHwasanMemTagOrTysan(CGM.getLangOpts().Sanitize))
113135
return;
114136
std::string QualName;
115137
llvm::raw_string_ostream OS(QualName);

0 commit comments

Comments
 (0)