mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01: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
5f73af13bd
commit
cd621c234a
@ -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