llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-support

Author: Matthew Levy (matthewlevy97)

<details>
<summary>Changes</summary>

RFC: 
https://discourse.llvm.org/t/rfc-implement-analysis-for-exploit-mitigation-coverage/84326

The goal of this stack is to provide a metric to audit the deployed mitigations 
in a binary and where they are enabled at function level granularity. This will 
enable tracking of where we do and don't have mitigations, versus the current 
approach of tracking where flags are passed. This is useful for several reasons 
including:

Providing assertions on mitigation deployment. For example, tools like checksec 
can alert of stack protector usage but cannot state which functions are enabled 
and why ("normal", "strong", or "all" option). The alternative to this method 
is binary analysis which has its own pros/cons.

Tracking of partial mitigation enablement. Some large projects might not want a 
boolean enablement of mitigations for multiple reasons (e.g., performance, 
size, etc), and so partial enablement is desired. This should provide accurate 
tracking over which functions have a given mitigation to better support 
incremental approaches.

Two flags are added to control this behavior:

Compile time -fmitigation-analysis to generate the metadata pertaining to 
mitigation enablement/disablement
Link time -mitigation-summary allows JSON output or embedding of custom section 
during LTO

---

Patch is 59.69 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/177390.diff


23 Files Affected:

- (modified) clang/include/clang/Basic/CodeGenOptions.def (+1) 
- (added) clang/include/clang/CodeGen/MitigationTagging.h (+35) 
- (modified) clang/include/clang/Options/Options.td (+9) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+11-1) 
- (modified) clang/lib/CodeGen/CGClass.cpp (+13) 
- (modified) clang/lib/CodeGen/CGDecl.cpp (+7) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+6) 
- (modified) clang/lib/CodeGen/CGExprCXX.cpp (+7) 
- (modified) clang/lib/CodeGen/CMakeLists.txt (+1) 
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+23) 
- (added) clang/lib/CodeGen/MitigationTagging.cpp (+67) 
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+3) 
- (modified) clang/unittests/CodeGen/CMakeLists.txt (+1) 
- (added) clang/unittests/CodeGen/MitigationTaggingTest.cpp (+287) 
- (added) llvm/include/llvm/Analysis/MitigationAnalysis.h (+80) 
- (added) llvm/include/llvm/Support/MitigationMarker.h (+44) 
- (modified) llvm/lib/Analysis/CMakeLists.txt (+1) 
- (added) llvm/lib/Analysis/MitigationAnalysis.cpp (+654) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (+1) 
- (modified) llvm/lib/Passes/PassBuilderPipelines.cpp (+12) 
- (modified) llvm/lib/Passes/PassRegistry.def (+1) 
- (modified) llvm/lib/Support/CMakeLists.txt (+1) 
- (added) llvm/lib/Support/MitigationMarker.cpp (+25) 


``````````diff
diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index 76a6463881c6f..fae379ace9068 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -187,6 +187,7 @@ CODEGENOPT(NoTypeCheck       , 1, 0, Benign) ///< Set when 
-Wa,--no-type-check i
 CODEGENOPT(MisExpect         , 1, 0, Benign) ///< Set when -Wmisexpect is 
enabled
 CODEGENOPT(EnableSegmentedStacks , 1, 0, Benign) ///< Set when -fsplit-stack 
is enabled.
 CODEGENOPT(StackClashProtector, 1, 0, Benign) ///< Set when 
-fstack-clash-protection is enabled.
+CODEGENOPT(MitigationAnalysis, 1, 0, Benign) ///< Set when 
-fmitigation-analysis is enabled.
 CODEGENOPT(NoImplicitFloat   , 1, 0, Benign) ///< Set when -mno-implicit-float 
is enabled.
 CODEGENOPT(NullPointerIsValid , 1, 0, Benign) ///< Assume Null pointer 
deference is defined.
 CODEGENOPT(OpenCLCorrectlyRoundedDivSqrt, 1, 0, Benign) ///< 
-cl-fp32-correctly-rounded-divide-sqrt
diff --git a/clang/include/clang/CodeGen/MitigationTagging.h 
b/clang/include/clang/CodeGen/MitigationTagging.h
new file mode 100644
index 0000000000000..3ccafdf8fa87a
--- /dev/null
+++ b/clang/include/clang/CodeGen/MitigationTagging.h
@@ -0,0 +1,35 @@
+//===--- MitigationTagging.h - Emit LLVM Code from ASTs for a Module 
------===//
+//
+// 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 enables tagging functions with metadata to indicate mitigations are
+// applied to them.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_MITIGATIONTAGGING_H
+#define LLVM_CLANG_LIB_CODEGEN_MITIGATIONTAGGING_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/Support/MitigationMarker.h"
+
+namespace clang {
+namespace CodeGen {
+
+class CodeGenFunction;
+
+void AttachMitigationMetadataToFunction(llvm::Function &F,
+                                        enum llvm::MitigationKey Key,
+                                        bool MitigationEnable);
+void AttachMitigationMetadataToFunction(CodeGenFunction &CGF,
+                                        enum llvm::MitigationKey Key,
+                                        bool MitigationEnable);
+
+} // namespace CodeGen
+} // namespace clang
+
+#endif
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c6841937c8d39..77572c95b32e5 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4207,6 +4207,15 @@ def ftrivial_auto_var_init_max_size : Joined<["-"], 
"ftrivial-auto-var-init-max-
   Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
   HelpText<"Stop initializing trivial automatic stack variables if var size 
exceeds the specified number of instances (in bytes)">,
   MarshallingInfoInt<LangOpts<"TrivialAutoVarInitMaxSize">>;
+defm mitigation_analysis
+    : BoolFOption<"mitigation-analysis", CodeGenOpts<"MitigationAnalysis">,
+                  DefaultFalse,
+                  PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
+                  NegFlag<SetFalse, [], [ClangOption], "Disable">,
+                  BothFlags<[], [ClangOption], " mitigation analysis">>,
+      DocBrief<"Instrument mitigations/preventions (Stack Protectors, "
+               "Auto-Var-Init, StackClashProtection, etc.) to analyze their "
+               "coverage">;
 def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>,
   Visibility<[ClangOption, CLOption, DXCOption]>,
   HelpText<"Emit full debug info for all types used by the program">;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 01be374422d93..845a167a5d159 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -28,6 +28,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/MitigationTagging.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Intrinsics.h"
@@ -154,6 +155,9 @@ static void initializeAlloca(CodeGenFunction &CGF, 
AllocaInst *AI, Value *Size,
   switch (CGF.getLangOpts().getTrivialAutoVarInit()) {
   case LangOptions::TrivialAutoVarInitKind::Uninitialized:
     // Nothing to initialize.
+    if (CGF.CGM.getCodeGenOpts().MitigationAnalysis)
+      AttachMitigationMetadataToFunction(CGF, MitigationKey::AUTO_VAR_INIT,
+                                         false);
     return;
   case LangOptions::TrivialAutoVarInitKind::Zero:
     Byte = CGF.Builder.getInt8(0x00);
@@ -165,8 +169,14 @@ static void initializeAlloca(CodeGenFunction &CGF, 
AllocaInst *AI, Value *Size,
     break;
   }
   }
-  if (CGF.CGM.stopAutoInit())
+
+  if (CGF.CGM.getCodeGenOpts().MitigationAnalysis)
+    AttachMitigationMetadataToFunction(CGF, MitigationKey::AUTO_VAR_INIT,
+                                       !CGF.CGM.stopAutoInit());
+
+  if (CGF.CGM.stopAutoInit()) {
     return;
+  }
   auto *I = CGF.Builder.CreateMemSet(AI, Byte, Size, AlignmentInBytes);
   I->addAnnotationMetadata("auto-init");
 }
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index f782b0cd17da4..8697a6ec8c8b9 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -26,6 +26,7 @@
 #include "clang/AST/StmtCXX.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGen/MitigationTagging.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/Support/SaveAndRestore.h"
@@ -2846,6 +2847,10 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const 
CXXRecordDecl *RD,
     llvm::Value *TypeTest =
         Builder.CreateCall(CGM.getIntrinsic(IID), {VTable, TypeId});
     Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
+
+    if (CGM.getCodeGenOpts().MitigationAnalysis)
+      AttachMitigationMetadataToFunction(*this, llvm::MitigationKey::CFI_VCALL,
+                                         SanOpts.has(SanitizerKind::CFIVCall));
   }
 }
 
@@ -3033,6 +3038,14 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
     EmitCheck(std::make_pair(CheckResult, CheckOrdinal), CheckHandler, {}, {});
   }
 
+  if (CGM.getCodeGenOpts().MitigationAnalysis) {
+    auto CFIVCallEnabled = SanOpts.has(SanitizerKind::CFIVCall) &&
+                           !getContext().getNoSanitizeList().containsType(
+                               SanitizerKind::CFIVCall, TypeName);
+    AttachMitigationMetadataToFunction(*this, llvm::MitigationKey::CFI_VCALL,
+                                       CFIVCallEnabled);
+  }
+
   return Builder.CreateBitCast(Builder.CreateExtractValue(CheckedLoad, 0),
                                VTableTy);
 }
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 8b1cd83af2396..8e984332334fc 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -33,6 +33,7 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGen/MitigationTagging.h"
 #include "clang/Sema/Sema.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/ValueTracking.h"
@@ -1988,6 +1989,12 @@ void CodeGenFunction::EmitAutoVarInit(const 
AutoVarEmission &emission) {
            ? LangOptions::TrivialAutoVarInitKind::Uninitialized
            : getContext().getLangOpts().getTrivialAutoVarInit());
 
+  if (CGM.getCodeGenOpts().MitigationAnalysis)
+    AttachMitigationMetadataToFunction(
+        *this, llvm::MitigationKey::AUTO_VAR_INIT,
+        trivialAutoVarInit !=
+            LangOptions::TrivialAutoVarInitKind::Uninitialized);
+
   auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) {
     if (trivialAutoVarInit ==
         LangOptions::TrivialAutoVarInitKind::Uninitialized)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 3bde8e1fa2ac3..2fe16eb85abff 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -37,6 +37,7 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/CodeGen/MitigationTagging.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
@@ -6603,6 +6604,11 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType,
 
   bool CFIUnchecked = CalleeType->hasPointeeToCFIUncheckedCalleeFunctionType();
 
+  if (CGM.getCodeGenOpts().MitigationAnalysis &&
+      (!TargetDecl || !isa<FunctionDecl>(TargetDecl)))
+    AttachMitigationMetadataToFunction(*this, llvm::MitigationKey::CFI_ICALL,
+                                       SanOpts.has(SanitizerKind::CFIICall));
+
   // If we are checking indirect calls and this call is indirect, check that 
the
   // function pointer is a member of the bit set for the function type.
   if (SanOpts.has(SanitizerKind::CFIICall) &&
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index ce2ed9026fa1f..6b1b1be2e56ae 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -19,6 +19,7 @@
 #include "TargetInfo.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGen/MitigationTagging.h"
 #include "llvm/IR/Intrinsics.h"
 
 using namespace clang;
@@ -416,6 +417,12 @@ RValue 
CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
       EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getBeginLoc());
     }
 
+    if (CGM.getCodeGenOpts().MitigationAnalysis &&
+        MD->getParent()->isDynamicClass()) {
+      AttachMitigationMetadataToFunction(*this, 
llvm::MitigationKey::CFI_NVCALL,
+                                         
SanOpts.has(SanitizerKind::CFINVCall));
+    }
+
     if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
       Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
     else if (!DevirtualizedMethod)
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index ad9ef91c781a8..459f483d86d7b 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -112,6 +112,7 @@ add_clang_library(clangCodeGen
   LinkInModulesPass.cpp
   MacroPPCallbacks.cpp
   MicrosoftCXXABI.cpp
+  MitigationTagging.cpp
   ModuleBuilder.cpp
   ObjectFilePCHContainerWriter.cpp
   PatternInit.cpp
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 1dcf94fc35e07..98518bbb60222 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -47,6 +47,7 @@
 #include "clang/Basic/Version.h"
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
+#include "clang/CodeGen/MitigationTagging.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -2747,6 +2748,28 @@ void 
CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
   else if (isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPReq))
     B.addAttribute(llvm::Attribute::StackProtectReq);
 
+  if (CodeGenOpts.MitigationAnalysis) {
+    AttachMitigationMetadataToFunction(
+        *F, llvm::MitigationKey::STACK_CLASH_PROTECTION,
+        CodeGenOpts.StackClashProtector);
+
+    if (!(D && D->hasAttr<NoStackProtectorAttr>())) {
+      bool stackProtectOn =
+          isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPOn);
+      bool stackProtectStrong =
+          isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPStrong);
+      bool stackProtectAll =
+          isStackProtectorOn(LangOpts, getTriple(), LangOptions::SSPReq);
+
+      AttachMitigationMetadataToFunction(
+          *F, llvm::MitigationKey::STACK_PROTECTOR, stackProtectOn);
+      AttachMitigationMetadataToFunction(
+          *F, llvm::MitigationKey::STACK_PROTECTOR_STRONG, stackProtectStrong);
+      AttachMitigationMetadataToFunction(
+          *F, llvm::MitigationKey::STACK_PROTECTOR_ALL, stackProtectAll);
+    }
+  }
+
   if (!D) {
     // Non-entry HLSL functions must always be inlined.
     if (getLangOpts().HLSL && !F->hasFnAttribute(llvm::Attribute::NoInline))
diff --git a/clang/lib/CodeGen/MitigationTagging.cpp 
b/clang/lib/CodeGen/MitigationTagging.cpp
new file mode 100644
index 0000000000000..e009d90a788a6
--- /dev/null
+++ b/clang/lib/CodeGen/MitigationTagging.cpp
@@ -0,0 +1,67 @@
+//===--- MitigationTagging.cpp - Emit LLVM Code from ASTs for a Module 
----===//
+//
+// 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 enables tagging functions with metadata to indicate mitigations are
+// applied to them.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/MitigationTagging.h"
+#include "CodeGenFunction.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/Support/FormatVariadic.h"
+
+namespace clang {
+namespace CodeGen {
+
+///
+/// Store metadata (tied to the function) related to enablement of mitigations.
+/// @param Key - identifier for the mitigation
+/// @param MitigationEnable - if the mitigation is enabled for the target
+/// function
+///
+void AttachMitigationMetadataToFunction(llvm::Function &F,
+                                        enum llvm::MitigationKey Key,
+                                        bool MitigationEnable) {
+  llvm::LLVMContext &Context = F.getContext();
+
+  const auto &MitigationToString = llvm::GetMitigationMetadataMapping();
+  auto KV = MitigationToString.find(Key);
+  if (KV == MitigationToString.end())
+    return;
+
+  unsigned KindID = Context.getMDKindID(KV->second);
+
+  // Only set once
+  if (!F.getMetadata(KindID)) {
+    llvm::Metadata *ValueMD =
+        llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+            llvm::Type::getInt1Ty(Context), MitigationEnable));
+    F.setMetadata(KindID, llvm::MDNode::get(Context, ValueMD));
+  }
+}
+
+///
+/// Store metadata (tied to the function) related to enablement of mitigations.
+/// Checks if MitigationAnalysis CodeGenOpt is set first and is a no-op if
+/// unset.
+/// @param Key - identifier for the mitigation
+/// @param MitigationEnable - if the mitigation is enabled for the target
+/// function
+///
+void AttachMitigationMetadataToFunction(CodeGenFunction &CGF,
+                                        enum llvm::MitigationKey Key,
+                                        bool MitigationEnable) {
+  if (CGF.CGM.getCodeGenOpts().MitigationAnalysis)
+    AttachMitigationMetadataToFunction(*(CGF.CurFn), Key, MitigationEnable);
+}
+
+} // namespace CodeGen
+} // namespace clang
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 0380568412e62..86f52df6bdc21 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6826,6 +6826,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   RenderSCPOptions(TC, Args, CmdArgs);
   RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
 
+  Args.addOptInFlag(CmdArgs, options::OPT_fmitigation_analysis,
+                    options::OPT_fno_mitigation_analysis);
+
   Args.AddLastArg(CmdArgs, options::OPT_fswift_async_fp_EQ);
 
   Args.addOptInFlag(CmdArgs, options::OPT_mstackrealign,
diff --git a/clang/unittests/CodeGen/CMakeLists.txt 
b/clang/unittests/CodeGen/CMakeLists.txt
index d4efb2230a054..3c36430e72550 100644
--- a/clang/unittests/CodeGen/CMakeLists.txt
+++ b/clang/unittests/CodeGen/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_unittest(ClangCodeGenTests
   DemangleTrapReasonInDebugInfo.cpp
   TBAAMetadataTest.cpp
   CheckTargetFeaturesTest.cpp
+  MitigationTaggingTest.cpp
   CLANG_LIBS
   clangAST
   clangBasic
diff --git a/clang/unittests/CodeGen/MitigationTaggingTest.cpp 
b/clang/unittests/CodeGen/MitigationTaggingTest.cpp
new file mode 100644
index 0000000000000..b9bb7c19f495d
--- /dev/null
+++ b/clang/unittests/CodeGen/MitigationTaggingTest.cpp
@@ -0,0 +1,287 @@
+#include "TestCompiler.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/MitigationTagging.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/MitigationMarker.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/Triple.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace clang::CodeGen;
+
+namespace {
+static const char TestProgram[] = "void SomeTestFunction(int x, int y)  "
+                                  "{                                    "
+                                  "   char buf[x];                      "
+                                  "   while(y)                          "
+                                  "      buf[y--] = 0;                  "
+                                  "}                                    ";
+static constexpr char TestFunctionMangledName[] = "_Z16SomeTestFunctionii";
+
+static int GetEnablementForMitigation(llvm::Function *FuncPtr,
+                                      StringRef MitigationStr) {
+  auto *MD = FuncPtr->getMetadata(MitigationStr);
+  // If not found, it just means the mitigation is likely not available
+  if (!MD)
+    return 0;
+
+  if (MD->getNumOperands() != 1)
+    return -1;
+
+  auto *ConstAsMeta = dyn_cast<ConstantAsMetadata>(MD->getOperand(0));
+  if (!ConstAsMeta)
+    return -2;
+
+  auto *Value = ConstAsMeta->getValue();
+
+  return Value->isOneValue();
+}
+
+TEST(MitigationTaggingTest, FlagDisabled) {
+  clang::LangOptions LO;
+  LO.CPlusPlus = 1;
+  LO.CPlusPlus11 = 1;
+
+  clang::CodeGenOptions CGO;
+
+  TestCompiler Compiler(LO, CGO);
+  Compiler.init(TestProgram);
+
+  clang::ParseAST(Compiler.compiler.getSema(), false, false);
+  auto M =
+      static_cast<clang::CodeGenerator &>(Compiler.compiler.getASTConsumer())
+          .GetModule();
+  auto FuncPtr = M->getFunction(TestFunctionMangledName);
+  ASSERT_TRUE(FuncPtr != nullptr);
+
+  auto Mapping = GetMitigationMetadataMapping();
+  auto *MD =
+      FuncPtr->getMetadata(Mapping[MitigationKey::STACK_CLASH_PROTECTION]);
+  ASSERT_TRUE(MD == nullptr);
+}
+
+TEST(MitigationTaggingTest, MetadataEnabledOnly) {
+  clang::CodeGenOptions CGO;
+  CGO.MitigationAnalysis = true;
+
+  clang::LangOptions LO;
+  LO.CPlusPlus = 1;
+  LO.CPlusPlus11 = 1;
+
+  TestCompiler Compiler(LO, CGO);
+  Compiler.init(TestProgram);
+
+  clang::ParseAST(Compiler.compiler.getSema(), false, false);
+  auto M =
+      static_cast<clang::CodeGenerator &>(Compiler.compiler.getASTConsumer())
+          .GetModule();
+  auto FuncPtr = M->getFunction(TestFunctionMangledName);
+  ASSERT_TRUE(FuncPtr != nullptr);
+
+  // Check that all mitigations disabled
+  for (const auto &[MitigationKey, MitigationStr] :
+       GetMitigationMetadataMapping()) {
+    EXPECT_EQ(GetEnablementForMitigation(FuncPtr, MitigationStr), 0);
+  }
+}
+
+TEST(MitigationTaggingTest, AutoVarInitZeroEnabled) {
+  clang::CodeGenOptions CGO;
+  CGO.MitigationAnalysis = true;
+
+  clang::LangOptions LO;
+  LO.CPlusPlus = 1;
+  LO.CPlusPlus11 = 1;
+  LO.setTrivialAutoVarInit(LangOptions::TrivialAutoVarInitKind::Zero);
+
+  TestCompiler Compiler(LO, CGO);
+  Compiler.init(TestProgram);
+
+  clang::ParseAST(Compiler.compiler.getSema(), false, false);
+  auto M =
+      static_cast<clang::CodeGenerator &>(Compiler.compiler.getASTConsumer())
+          .GetModule();
+  auto FuncPtr = M->getFunction(TestFunctionMangledName);
+  ASSERT_TRUE(FuncPtr != nullptr);
+
+  // Check that the correct mitigations are enabled
+  auto mitigation...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/177390
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to