[clang] e0b469f - [clang-cl][sanitizer] Add -fsanitize-address-use-after-return to clang.

Kevin Athey via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 11 12:07:46 PDT 2021


Author: Kevin Athey
Date: 2021-06-11T12:07:35-07:00
New Revision: e0b469ffa142353fc90bfc6eadb638a805ebed75

URL: https://github.com/llvm/llvm-project/commit/e0b469ffa142353fc90bfc6eadb638a805ebed75
DIFF: https://github.com/llvm/llvm-project/commit/e0b469ffa142353fc90bfc6eadb638a805ebed75.diff

LOG: [clang-cl][sanitizer] Add -fsanitize-address-use-after-return to clang.

Also:
  - add driver test (fsanitize-use-after-return.c)
  - add basic IR test (asan-use-after-return.cpp)
  - (NFC) cleaned up logic for generating table of __asan_stack_malloc
    depending on flag.

for issue: https://github.com/google/sanitizers/issues/1394

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D104076

Added: 
    clang/test/CodeGen/asan-use-after-return.cpp
    clang/test/Driver/fsanitize-use-after-return.c

Modified: 
    clang/include/clang/Basic/CodeGenOptions.def
    clang/include/clang/Basic/Sanitizers.h
    clang/include/clang/Driver/Options.td
    clang/include/clang/Driver/SanitizerArgs.h
    clang/lib/Basic/Sanitizers.cpp
    clang/lib/CodeGen/BackendUtil.cpp
    clang/lib/Driver/SanitizerArgs.cpp
    clang/test/Driver/cl-options.c
    llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
    llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index b4699805eb40..e3202cf88756 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -212,6 +212,10 @@ CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-
 CODEGENOPT(SaveTempLabels    , 1, 0) ///< Save temporary labels.
 CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection
                                                 ///< in AddressSanitizer
+ENUM_CODEGENOPT(SanitizeAddressUseAfterReturn,
+                llvm::AsanDetectStackUseAfterReturnMode, 2,
+                llvm::AsanDetectStackUseAfterReturnMode::Runtime
+                ) ///< Set detection mode for stack-use-after-return.
 CODEGENOPT(SanitizeAddressPoisonCustomArrayCookie, 1,
            0) ///< Enable poisoning operator new[] which is not a replaceable
               ///< global allocation function in AddressSanitizer

diff  --git a/clang/include/clang/Basic/Sanitizers.h b/clang/include/clang/Basic/Sanitizers.h
index 82e5a73dee2e..b12a3b7821d7 100644
--- a/clang/include/clang/Basic/Sanitizers.h
+++ b/clang/include/clang/Basic/Sanitizers.h
@@ -192,6 +192,12 @@ StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
 
 llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
 
+StringRef AsanDetectStackUseAfterReturnModeToString(
+    llvm::AsanDetectStackUseAfterReturnMode mode);
+
+llvm::AsanDetectStackUseAfterReturnMode
+AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr);
+
 } // namespace clang
 
 #endif // LLVM_CLANG_BASIC_SANITIZERS_H

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 6f3169644396..3968aa3431ea 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1587,6 +1587,16 @@ defm sanitize_address_use_after_scope : BoolOption<"f", "sanitize-address-use-af
   PosFlag<SetTrue, [], "Enable">, NegFlag<SetFalse, [CoreOption, NoXarchOption], "Disable">,
   BothFlags<[], " use-after-scope detection in AddressSanitizer">>,
   Group<f_clang_Group>;
+def sanitize_address_use_after_return_EQ
+  : Joined<["-"], "fsanitize-address-use-after-return=">,
+    MetaVarName<"<mode>">,
+    Flags<[CC1Option]>,
+    HelpText<"Select the mode of detecting stack use-after-return in AddressSanitizer">,
+    Group<f_clang_Group>,
+    Values<"never,runtime,always">,
+    NormalizedValuesScope<"llvm::AsanDetectStackUseAfterReturnMode">,
+    NormalizedValues<["Never", "Runtime", "Always"]>,
+    MarshallingInfoEnum<CodeGenOpts<"SanitizeAddressUseAfterReturn">, "Runtime">;
 defm sanitize_address_poison_custom_array_cookie : BoolOption<"f", "sanitize-address-poison-custom-array-cookie",
   CodeGenOpts<"SanitizeAddressPoisonCustomArrayCookie">, DefaultFalse,
   PosFlag<SetTrue, [], "Enable">, NegFlag<SetFalse, [], "Disable">,

diff  --git a/clang/include/clang/Driver/SanitizerArgs.h b/clang/include/clang/Driver/SanitizerArgs.h
index adfc26382f60..63a195fdf753 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -12,6 +12,7 @@
 #include "clang/Driver/Types.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
 #include <string>
 #include <vector>
 
@@ -58,6 +59,8 @@ class SanitizerArgs {
   bool ImplicitCfiRuntime = false;
   bool NeedsMemProfRt = false;
   bool HwasanUseAliases = false;
+  llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
+      llvm::AsanDetectStackUseAfterReturnMode::Invalid;
 
 public:
   /// Parses the sanitizer arguments from an argument list.

diff  --git a/clang/lib/Basic/Sanitizers.cpp b/clang/lib/Basic/Sanitizers.cpp
index 3a3b24a62e11..7d903c8fdf5e 100644
--- a/clang/lib/Basic/Sanitizers.cpp
+++ b/clang/lib/Basic/Sanitizers.cpp
@@ -88,4 +88,28 @@ llvm::AsanDtorKind AsanDtorKindFromString(StringRef kindStr) {
       .Default(llvm::AsanDtorKind::Invalid);
 }
 
+StringRef AsanDetectStackUseAfterReturnModeToString(
+    llvm::AsanDetectStackUseAfterReturnMode mode) {
+  switch (mode) {
+  case llvm::AsanDetectStackUseAfterReturnMode::Always:
+    return "always";
+  case llvm::AsanDetectStackUseAfterReturnMode::Runtime:
+    return "runtime";
+  case llvm::AsanDetectStackUseAfterReturnMode::Never:
+    return "never";
+  case llvm::AsanDetectStackUseAfterReturnMode::Invalid:
+    return "invalid";
+  }
+  return "invalid";
+}
+
+llvm::AsanDetectStackUseAfterReturnMode
+AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr) {
+  return llvm::StringSwitch<llvm::AsanDetectStackUseAfterReturnMode>(modeStr)
+      .Case("always", llvm::AsanDetectStackUseAfterReturnMode::Always)
+      .Case("runtime", llvm::AsanDetectStackUseAfterReturnMode::Runtime)
+      .Case("never", llvm::AsanDetectStackUseAfterReturnMode::Never)
+      .Default(llvm::AsanDetectStackUseAfterReturnMode::Invalid);
+}
+
 } // namespace clang

diff  --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index ad63ef63e5b1..bafcf7cb8a8f 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -65,6 +65,7 @@
 #include "llvm/Transforms/InstCombine/InstCombine.h"
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
 #include "llvm/Transforms/Instrumentation/BoundsChecking.h"
 #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
@@ -288,8 +289,10 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
   bool UseOdrIndicator = CGOpts.SanitizeAddressUseOdrIndicator;
   bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts);
   llvm::AsanDtorKind DestructorKind = CGOpts.getSanitizeAddressDtor();
+  llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
+      CGOpts.getSanitizeAddressUseAfterReturn();
   PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover,
-                                            UseAfterScope));
+                                            UseAfterScope, UseAfterReturn));
   PM.add(createModuleAddressSanitizerLegacyPassPass(
       /*CompileKernel*/ false, Recover, UseGlobalsGC, UseOdrIndicator,
       DestructorKind));
@@ -298,7 +301,8 @@ static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
 static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
                                             legacy::PassManagerBase &PM) {
   PM.add(createAddressSanitizerFunctionPass(
-      /*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false));
+      /*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false,
+      /*UseAfterReturn*/ llvm::AsanDetectStackUseAfterReturnMode::Never));
   PM.add(createModuleAddressSanitizerLegacyPassPass(
       /*CompileKernel*/ true, /*Recover*/ true, /*UseGlobalsGC*/ true,
       /*UseOdrIndicator*/ false));
@@ -1144,12 +1148,14 @@ static void addSanitizers(const Triple &TargetTriple,
         bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;
         llvm::AsanDtorKind DestructorKind =
             CodeGenOpts.getSanitizeAddressDtor();
+        llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
+            CodeGenOpts.getSanitizeAddressUseAfterReturn();
         MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
         MPM.addPass(ModuleAddressSanitizerPass(
             CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator,
             DestructorKind));
-        MPM.addPass(createModuleToFunctionPassAdaptor(
-            AddressSanitizerPass(CompileKernel, Recover, UseAfterScope)));
+        MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
+            CompileKernel, Recover, UseAfterScope, UseAfterReturn)));
       }
     };
     ASanPass(SanitizerKind::Address, false);

diff  --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 244d22b08ca0..68975aafcd37 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Support/SpecialCaseList.h"
 #include "llvm/Support/TargetParser.h"
 #include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
 #include <memory>
 
 using namespace clang;
@@ -841,6 +842,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
       AsanDtorKind = parsedAsanDtorKind;
     }
 
+    if (const auto *Arg = Args.getLastArg(
+            options::OPT_sanitize_address_use_after_return_EQ)) {
+      auto parsedAsanUseAfterReturn =
+          AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());
+      if (parsedAsanUseAfterReturn ==
+          llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
+        TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
+            << Arg->getOption().getName() << Arg->getValue();
+      }
+      AsanUseAfterReturn = parsedAsanUseAfterReturn;
+    }
+
   } else {
     AsanUseAfterScope = false;
     // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
@@ -1112,6 +1125,12 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
                                          AsanDtorKindToString(AsanDtorKind)));
   }
 
+  if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
+    CmdArgs.push_back(Args.MakeArgString(
+        "-fsanitize-address-use-after-return=" +
+        AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
+  }
+
   if (!HwasanAbi.empty()) {
     CmdArgs.push_back("-default-function-attr");
     CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));

diff  --git a/clang/test/CodeGen/asan-use-after-return.cpp b/clang/test/CodeGen/asan-use-after-return.cpp
new file mode 100644
index 000000000000..1b84f7b6ddf3
--- /dev/null
+++ b/clang/test/CodeGen/asan-use-after-return.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
+// RUN:     | FileCheck %s --check-prefixes=CHECK-RUNTIME \
+// RUN:         --implicit-check-not="__asan_stack_malloc_always_"
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
+// RUN:         -fsanitize-address-use-after-return=runtime \
+// RUN:     | FileCheck %s --check-prefixes=CHECK-RUNTIME \
+// RUN:         --implicit-check-not="__asan_stack_malloc_always_"
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
+// RUN:         -fsanitize-address-use-after-return=always \
+// RUN:     | FileCheck %s --check-prefixes=CHECK-ALWAYS \
+// RUN:         --implicit-check-not=__asan_option_detect_stack_use_after_return \
+// RUN:         --implicit-check-not="__asan_stack_malloc_{{[0-9]}}"
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-linux %s \
+// RUN:         -fsanitize-address-use-after-return=never \
+// RUN:     | FileCheck %s \
+// RUN:         --implicit-check-not=__asan_option_detect_stack_use_after_return \
+// RUN:         --implicit-check-not="__asan_stack_malloc_"
+
+// CHECK-RUNTIME: load{{.*}}@__asan_option_detect_stack_use_after_return
+// CHECK-RUNTIME: call{{.*}}__asan_stack_malloc_0
+// CHECK-ALWAYS: call{{.*}}__asan_stack_malloc_always_0
+
+int *function1() {
+  int x = 0;
+
+#pragma clang diagnostic ignored "-Wreturn-stack-address"
+  return &x;
+}
+
+int main() {
+  auto px = function1();
+  return 0;
+}

diff  --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index d1bd6f5146b4..258ac451fee0 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -452,7 +452,6 @@
 // RUN:     /FAs \
 // RUN:     /FAu \
 // RUN:     /favor:blend \
-// RUN:     /fsanitize-address-use-after-return \
 // RUN:     /fno-sanitize-address-vcasan-lib \
 // RUN:     /Fifoo \
 // RUN:     /Fmfoo \

diff  --git a/clang/test/Driver/fsanitize-use-after-return.c b/clang/test/Driver/fsanitize-use-after-return.c
new file mode 100644
index 000000000000..f262fa2ef0c7
--- /dev/null
+++ b/clang/test/Driver/fsanitize-use-after-return.c
@@ -0,0 +1,30 @@
+// Option should not be passed to the frontend by default.
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address %s \
+// RUN:   -### 2>&1 | \
+// RUN:   FileCheck %s
+// CHECK-NOT: -fsanitize-address-use-after-return
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-use-after-return=never %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-NEVER-ARG %s
+// CHECK-NEVER-ARG: "-fsanitize-address-use-after-return=never"
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-use-after-return=runtime %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-RUNTIME %s
+// CHECK-RUNTIME: "-fsanitize-address-use-after-return=runtime"
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-use-after-return=always %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-ALWAYS-ARG %s
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-use-after-return=never \
+// RUN:   -fsanitize-address-use-after-return=always %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-ALWAYS-ARG %s
+// CHECK-ALWAYS-ARG: "-fsanitize-address-use-after-return=always"
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-use-after-return=bad_arg %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-INVALID-ARG %s
+// CHECK-INVALID-ARG: error: unsupported argument 'bad_arg' to option 'fsanitize-address-use-after-return='

diff  --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
index 10b5d2d000b0..3781253d2694 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h
@@ -99,9 +99,11 @@ class ASanGlobalsMetadataAnalysis
 /// surrounding requested memory to be checked for invalid accesses.
 class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
 public:
-  explicit AddressSanitizerPass(bool CompileKernel = false,
-                                bool Recover = false,
-                                bool UseAfterScope = false);
+  explicit AddressSanitizerPass(
+      bool CompileKernel = false, bool Recover = false,
+      bool UseAfterScope = false,
+      AsanDetectStackUseAfterReturnMode UseAfterReturn =
+          AsanDetectStackUseAfterReturnMode::Runtime);
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
   static bool isRequired() { return true; }
 
@@ -109,6 +111,7 @@ class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> {
   bool CompileKernel;
   bool Recover;
   bool UseAfterScope;
+  AsanDetectStackUseAfterReturnMode UseAfterReturn;
 };
 
 /// Public interface to the address sanitizer module pass for instrumenting code
@@ -135,9 +138,11 @@ class ModuleAddressSanitizerPass
 };
 
 // Insert AddressSanitizer (address sanity checking) instrumentation
-FunctionPass *createAddressSanitizerFunctionPass(bool CompileKernel = false,
-                                                 bool Recover = false,
-                                                 bool UseAfterScope = false);
+FunctionPass *createAddressSanitizerFunctionPass(
+    bool CompileKernel = false, bool Recover = false,
+    bool UseAfterScope = false,
+    AsanDetectStackUseAfterReturnMode UseAfterReturn =
+        AsanDetectStackUseAfterReturnMode::Runtime);
 ModulePass *createModuleAddressSanitizerLegacyPassPass(
     bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true,
     bool UseOdrIndicator = true,

diff  --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index c9f7693ef8da..dd26d3462eb7 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -633,17 +633,24 @@ char ASanGlobalsMetadataWrapperPass::ID = 0;
 struct AddressSanitizer {
   AddressSanitizer(Module &M, const GlobalsMetadata *GlobalsMD,
                    bool CompileKernel = false, bool Recover = false,
-                   bool UseAfterScope = false)
+                   bool UseAfterScope = false,
+                   AsanDetectStackUseAfterReturnMode UseAfterReturn =
+                       AsanDetectStackUseAfterReturnMode::Runtime)
       : CompileKernel(ClEnableKasan.getNumOccurrences() > 0 ? ClEnableKasan
                                                             : CompileKernel),
         Recover(ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover),
-        UseAfterScope(UseAfterScope || ClUseAfterScope), GlobalsMD(*GlobalsMD) {
+        UseAfterScope(UseAfterScope || ClUseAfterScope),
+        UseAfterReturn(ClUseAfterReturn.getNumOccurrences() ? ClUseAfterReturn
+                                                            : UseAfterReturn),
+        GlobalsMD(*GlobalsMD) {
     C = &(M.getContext());
     LongSize = M.getDataLayout().getPointerSizeInBits();
     IntptrTy = Type::getIntNTy(*C, LongSize);
     TargetTriple = Triple(M.getTargetTriple());
 
     Mapping = getShadowMapping(TargetTriple, LongSize, this->CompileKernel);
+
+    assert(this->UseAfterReturn != AsanDetectStackUseAfterReturnMode::Invalid);
   }
 
   uint64_t getAllocaSizeInBytes(const AllocaInst &AI) const {
@@ -727,6 +734,7 @@ struct AddressSanitizer {
   bool CompileKernel;
   bool Recover;
   bool UseAfterScope;
+  AsanDetectStackUseAfterReturnMode UseAfterReturn;
   Type *IntptrTy;
   ShadowMapping Mapping;
   FunctionCallee AsanHandleNoReturnFunc;
@@ -754,11 +762,13 @@ class AddressSanitizerLegacyPass : public FunctionPass {
 public:
   static char ID;
 
-  explicit AddressSanitizerLegacyPass(bool CompileKernel = false,
-                                      bool Recover = false,
-                                      bool UseAfterScope = false)
+  explicit AddressSanitizerLegacyPass(
+      bool CompileKernel = false, bool Recover = false,
+      bool UseAfterScope = false,
+      AsanDetectStackUseAfterReturnMode UseAfterReturn =
+          AsanDetectStackUseAfterReturnMode::Runtime)
       : FunctionPass(ID), CompileKernel(CompileKernel), Recover(Recover),
-        UseAfterScope(UseAfterScope) {
+        UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn) {
     initializeAddressSanitizerLegacyPassPass(*PassRegistry::getPassRegistry());
   }
 
@@ -777,7 +787,7 @@ class AddressSanitizerLegacyPass : public FunctionPass {
     const TargetLibraryInfo *TLI =
         &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
     AddressSanitizer ASan(*F.getParent(), &GlobalsMD, CompileKernel, Recover,
-                          UseAfterScope);
+                          UseAfterScope, UseAfterReturn);
     return ASan.instrumentFunction(F, TLI);
   }
 
@@ -785,6 +795,7 @@ class AddressSanitizerLegacyPass : public FunctionPass {
   bool CompileKernel;
   bool Recover;
   bool UseAfterScope;
+  AsanDetectStackUseAfterReturnMode UseAfterReturn;
 };
 
 class ModuleAddressSanitizer {
@@ -1227,10 +1238,11 @@ GlobalsMetadata ASanGlobalsMetadataAnalysis::run(Module &M,
   return GlobalsMetadata(M);
 }
 
-AddressSanitizerPass::AddressSanitizerPass(bool CompileKernel, bool Recover,
-                                           bool UseAfterScope)
+AddressSanitizerPass::AddressSanitizerPass(
+    bool CompileKernel, bool Recover, bool UseAfterScope,
+    AsanDetectStackUseAfterReturnMode UseAfterReturn)
     : CompileKernel(CompileKernel), Recover(Recover),
-      UseAfterScope(UseAfterScope) {}
+      UseAfterScope(UseAfterScope), UseAfterReturn(UseAfterReturn) {}
 
 PreservedAnalyses AddressSanitizerPass::run(Function &F,
                                             AnalysisManager<Function> &AM) {
@@ -1238,7 +1250,8 @@ PreservedAnalyses AddressSanitizerPass::run(Function &F,
   Module &M = *F.getParent();
   if (auto *R = MAMProxy.getCachedResult<ASanGlobalsMetadataAnalysis>(M)) {
     const TargetLibraryInfo *TLI = &AM.getResult<TargetLibraryAnalysis>(F);
-    AddressSanitizer Sanitizer(M, R, CompileKernel, Recover, UseAfterScope);
+    AddressSanitizer Sanitizer(M, R, CompileKernel, Recover, UseAfterScope,
+                               UseAfterReturn);
     if (Sanitizer.instrumentFunction(F, TLI))
       return PreservedAnalyses::none();
     return PreservedAnalyses::all();
@@ -1285,11 +1298,12 @@ INITIALIZE_PASS_END(
     "AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false,
     false)
 
-FunctionPass *llvm::createAddressSanitizerFunctionPass(bool CompileKernel,
-                                                       bool Recover,
-                                                       bool UseAfterScope) {
+FunctionPass *llvm::createAddressSanitizerFunctionPass(
+    bool CompileKernel, bool Recover, bool UseAfterScope,
+    AsanDetectStackUseAfterReturnMode UseAfterReturn) {
   assert(!CompileKernel || Recover);
-  return new AddressSanitizerLegacyPass(CompileKernel, Recover, UseAfterScope);
+  return new AddressSanitizerLegacyPass(CompileKernel, Recover, UseAfterScope,
+                                        UseAfterReturn);
 }
 
 char ModuleAddressSanitizerLegacyPass::ID = 0;
@@ -2953,33 +2967,20 @@ bool AddressSanitizer::LooksLikeCodeInBug11395(Instruction *I) {
 
 void FunctionStackPoisoner::initializeCallbacks(Module &M) {
   IRBuilder<> IRB(*C);
-  switch (ClUseAfterReturn) {
-  case AsanDetectStackUseAfterReturnMode::Always:
-    for (int i = 0; i <= kMaxAsanStackMallocSizeClass; i++) {
-      std::string Suffix = itostr(i);
-      AsanStackMallocFunc[i] = M.getOrInsertFunction(
-          kAsanStackMallocAlwaysNameTemplate + Suffix, IntptrTy, IntptrTy);
-      AsanStackFreeFunc[i] =
-          M.getOrInsertFunction(kAsanStackFreeNameTemplate + Suffix,
-                                IRB.getVoidTy(), IntptrTy, IntptrTy);
-    }
-    break;
-  case AsanDetectStackUseAfterReturnMode::Runtime:
-    for (int i = 0; i <= kMaxAsanStackMallocSizeClass; i++) {
-      std::string Suffix = itostr(i);
-      AsanStackMallocFunc[i] = M.getOrInsertFunction(
-          kAsanStackMallocNameTemplate + Suffix, IntptrTy, IntptrTy);
-      AsanStackFreeFunc[i] =
+  if (ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Always ||
+      ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Runtime) {
+    const char *MallocNameTemplate =
+        ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Always
+            ? kAsanStackMallocAlwaysNameTemplate
+            : kAsanStackMallocNameTemplate;
+    for (int Index = 0; Index <= kMaxAsanStackMallocSizeClass; Index++) {
+      std::string Suffix = itostr(Index);
+      AsanStackMallocFunc[Index] = M.getOrInsertFunction(
+          MallocNameTemplate + Suffix, IntptrTy, IntptrTy);
+      AsanStackFreeFunc[Index] =
           M.getOrInsertFunction(kAsanStackFreeNameTemplate + Suffix,
                                 IRB.getVoidTy(), IntptrTy, IntptrTy);
     }
-    break;
-  case AsanDetectStackUseAfterReturnMode::Never:
-    // Do Nothing
-    break;
-  case AsanDetectStackUseAfterReturnMode::Invalid:
-    // Do Nothing
-    break;
   }
   if (ASan.UseAfterScope) {
     AsanPoisonStackMemoryFunc = M.getOrInsertFunction(
@@ -3331,7 +3332,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
   LLVM_DEBUG(dbgs() << DescriptionString << " --- " << L.FrameSize << "\n");
   uint64_t LocalStackSize = L.FrameSize;
   bool DoStackMalloc =
-      ClUseAfterReturn != AsanDetectStackUseAfterReturnMode::Never &&
+      ASan.UseAfterReturn != AsanDetectStackUseAfterReturnMode::Never &&
       !ASan.CompileKernel && LocalStackSize <= kMaxStackMallocSize;
   bool DoDynamicAlloca = ClDynamicAllocaStack;
   // Don't do dynamic alloca or stack malloc if:
@@ -3354,7 +3355,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
   if (DoStackMalloc) {
     LocalStackBaseAlloca =
         IRB.CreateAlloca(IntptrTy, nullptr, "asan_local_stack_base");
-    if (ClUseAfterReturn == AsanDetectStackUseAfterReturnMode::Runtime) {
+    if (ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode::Runtime) {
       // void *FakeStack = __asan_option_detect_stack_use_after_return
       //     ? __asan_stack_malloc_N(LocalStackSize)
       //     : nullptr;
@@ -3377,7 +3378,7 @@ void FunctionStackPoisoner::processStaticAllocas() {
       FakeStack = createPHI(IRB, UseAfterReturnIsEnabled, FakeStackValue, Term,
                             ConstantInt::get(IntptrTy, 0));
     } else {
-      // assert(ClUseAfterReturn == AsanDetectStackUseAfterReturnMode:Always)
+      // assert(ASan.UseAfterReturn == AsanDetectStackUseAfterReturnMode:Always)
       // void *FakeStack = __asan_stack_malloc_N(LocalStackSize);
       // void *LocalStackBase = (FakeStack) ? FakeStack :
       //                        alloca(LocalStackSize);


        


More information about the cfe-commits mailing list