1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +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:
Kevin Athey 2021-06-11 10:13:10 -07:00
parent 5f73af13bd
commit cd621c234a
2 changed files with 54 additions and 48 deletions

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