diff options
| author | Vedant Kumar <vsk@apple.com> | 2017-06-23 21:32:38 +0000 |
|---|---|---|
| committer | Vedant Kumar <vsk@apple.com> | 2017-06-23 21:32:38 +0000 |
| commit | c34d343f15373dde087897d33fe3173726dd4cf1 (patch) | |
| tree | 36ede4fd471c6f0cc0e76502eb6671951292d07f /clang/lib/CodeGen/CGCall.cpp | |
| parent | 77a2e6b198550e2e4bccf8b724bc1b7f8fa819ec (diff) | |
| download | bcm5719-llvm-c34d343f15373dde087897d33fe3173726dd4cf1.tar.gz bcm5719-llvm-c34d343f15373dde087897d33fe3173726dd4cf1.zip | |
[ubsan] Improve diagnostics for return value checks (clang)
This patch makes ubsan's nonnull return value diagnostics more precise,
which makes the diagnostics more useful when there are multiple return
statements in a function. Example:
1 |__attribute__((returns_nonnull)) char *foo() {
2 | if (...) {
3 | return expr_which_might_evaluate_to_null();
4 | } else {
5 | return another_expr_which_might_evaluate_to_null();
6 | }
7 |} // <- The current diagnostic always points here!
runtime error: Null returned from Line 7, Column 2!
With this patch, the diagnostic would point to either Line 3, Column 5
or Line 5, Column 5.
This is done by emitting source location metadata for each return
statement in a sanitized function. The runtime is passed a pointer to
the appropriate metadata so that it can prepare and deduplicate reports.
Compiler-rt patch (with more tests): https://reviews.llvm.org/D34298
Differential Revision: https://reviews.llvm.org/D34299
llvm-svn: 306163
Diffstat (limited to 'clang/lib/CodeGen/CGCall.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0e5ccc0d9fc..38d520a2beb 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2906,7 +2906,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, llvm::Instruction *Ret; if (RV) { - EmitReturnValueCheck(RV, EndLoc); + EmitReturnValueCheck(RV); Ret = Builder.CreateRet(RV); } else { Ret = Builder.CreateRetVoid(); @@ -2916,8 +2916,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, Ret->setDebugLoc(std::move(RetDbgLoc)); } -void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV, - SourceLocation EndLoc) { +void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) { // A current decl may not be available when emitting vtable thunks. if (!CurCodeDecl) return; @@ -2950,27 +2949,30 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV, SanitizerScope SanScope(this); - llvm::BasicBlock *Check = nullptr; - llvm::BasicBlock *NoCheck = nullptr; - if (requiresReturnValueNullabilityCheck()) { - // Before doing the nullability check, make sure that the preconditions for - // the check are met. - Check = createBasicBlock("nullcheck"); - NoCheck = createBasicBlock("no.nullcheck"); - Builder.CreateCondBr(RetValNullabilityPrecondition, Check, NoCheck); - EmitBlock(Check); - } + // Make sure the "return" source location is valid. If we're checking a + // nullability annotation, make sure the preconditions for the check are met. + llvm::BasicBlock *Check = createBasicBlock("nullcheck"); + llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck"); + llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load"); + llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr); + if (requiresReturnValueNullabilityCheck()) + CanNullCheck = + Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition); + Builder.CreateCondBr(CanNullCheck, Check, NoCheck); + EmitBlock(Check); - // Now do the null check. If the returns_nonnull attribute is present, this - // is done unconditionally. + // Now do the null check. llvm::Value *Cond = Builder.CreateIsNotNull(RV); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(EndLoc), EmitCheckSourceLocation(AttrLoc), - }; - EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None); + llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)}; + llvm::Value *DynamicData[] = {SLocPtr}; + EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData); - if (requiresReturnValueNullabilityCheck()) - EmitBlock(NoCheck); + EmitBlock(NoCheck); + +#ifndef NDEBUG + // The return location should not be used after the check has been emitted. + ReturnLocation = Address::invalid(); +#endif } static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) { |

