summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGCall.cpp
diff options
context:
space:
mode:
authorJulian Lettner <jlettner@apple.com>2019-01-30 23:42:13 +0000
committerJulian Lettner <jlettner@apple.com>2019-01-30 23:42:13 +0000
commit8280c1e23ed998a439f26b7637d2dc82ee2f5d3e (patch)
treee73ae60660e8546d560ee7abb472149c041bd652 /clang/lib/CodeGen/CGCall.cpp
parentbe589423d8ea24370bb087a2a05f75100d1be76d (diff)
downloadbcm5719-llvm-8280c1e23ed998a439f26b7637d2dc82ee2f5d3e.tar.gz
bcm5719-llvm-8280c1e23ed998a439f26b7637d2dc82ee2f5d3e.zip
[Sanitizers] UBSan unreachable incompatible with ASan in the presence of `noreturn` calls
Summary: UBSan wants to detect when unreachable code is actually reached, so it adds instrumentation before every unreachable instruction. However, the optimizer will remove code after calls to functions marked with noreturn. To avoid this UBSan removes noreturn from both the call instruction as well as from the function itself. Unfortunately, ASan relies on this annotation to unpoison the stack by inserting calls to _asan_handle_no_return before noreturn functions. This is important for functions that do not return but access the the stack memory, e.g., unwinder functions *like* longjmp (longjmp itself is actually "double-proofed" via its interceptor). The result is that when ASan and UBSan are combined, the noreturn attributes are missing and ASan cannot unpoison the stack, so it has false positives when stack unwinding is used. Changes: Clang-CodeGen now directly insert calls to `__asan_handle_no_return` when a call to a noreturn function is encountered and both UBsan-unreachable and ASan are enabled. This allows UBSan to continue removing the noreturn attribute from functions without any changes to the ASan pass. Previously generated code: ``` call void @longjmp call void @__asan_handle_no_return call void @__ubsan_handle_builtin_unreachable ``` Generated code (for now): ``` call void @__asan_handle_no_return call void @longjmp call void @__asan_handle_no_return call void @__ubsan_handle_builtin_unreachable ``` rdar://problem/40723397 Reviewers: delcypher, eugenis, vsk Differential Revision: https://reviews.llvm.org/D57278 llvm-svn: 352690
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp13
1 files changed, 13 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 893a6f2f902..655c75c01f6 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4398,10 +4398,23 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// Strip away the noreturn attribute to better diagnose unreachable UB.
if (SanOpts.has(SanitizerKind::Unreachable)) {
+ // Also remove from function since CI->hasFnAttr(..) also checks attributes
+ // of the called function.
if (auto *F = CI->getCalledFunction())
F->removeFnAttr(llvm::Attribute::NoReturn);
CI->removeAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoReturn);
+
+ // Avoid incompatibility with ASan which relies on the `noreturn`
+ // attribute to insert handler calls.
+ if (SanOpts.has(SanitizerKind::Address)) {
+ SanitizerScope SanScope(this);
+ Builder.SetInsertPoint(CI);
+ auto *FnType = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ auto *Fn = CGM.CreateRuntimeFunction(FnType, "__asan_handle_no_return");
+ EmitNounwindRuntimeCall(Fn);
+ Builder.SetInsertPoint(CI->getParent());
+ }
}
EmitUnreachable(Loc);
OpenPOWER on IntegriCloud