mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
[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:
parent
c0c5a98b2c
commit
e0b469ffa1
@ -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
|
||||
|
@ -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
|
||||
|
@ -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">,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
33
clang/test/CodeGen/asan-use-after-return.cpp
Normal file
33
clang/test/CodeGen/asan-use-after-return.cpp
Normal 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;
|
||||
}
|
@ -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 \
|
||||
|
30
clang/test/Driver/fsanitize-use-after-return.c
Normal file
30
clang/test/Driver/fsanitize-use-after-return.c
Normal 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='
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user