[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
This commit is contained in:
Kevin Athey 2021-06-11 10:13:10 -07:00
parent c0c5a98b2c
commit e0b469ffa1
12 changed files with 193 additions and 53 deletions

View File

@ -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

View File

@ -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

View File

@ -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">,

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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));

View File

@ -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;
}

View File

@ -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 \

View File

@ -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='

View File

@ -99,9 +99,11 @@ private:
/// 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 @@ private:
bool CompileKernel;
bool Recover;
bool UseAfterScope;
AsanDetectStackUseAfterReturnMode UseAfterReturn;
};
/// Public interface to the address sanitizer module pass for instrumenting code
@ -135,9 +138,11 @@ private:
};
// 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,

View File

@ -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 @@ private:
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 @@ public:
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 @@ private:
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] =
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::Runtime:
for (int i = 0; i <= kMaxAsanStackMallocSizeClass; i++) {
std::string Suffix = itostr(i);
AsanStackMallocFunc[i] = M.getOrInsertFunction(
kAsanStackMallocNameTemplate + Suffix, IntptrTy, IntptrTy);
AsanStackFreeFunc[i] =
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);