r215485 - [UBSan] Add returns-nonnull sanitizer.
Alexey Samsonov
vonosmas at gmail.com
Tue Aug 12 17:26:40 PDT 2014
Author: samsonov
Date: Tue Aug 12 19:26:40 2014
New Revision: 215485
URL: http://llvm.org/viewvc/llvm-project?rev=215485&view=rev
Log:
[UBSan] Add returns-nonnull sanitizer.
Summary:
This patch adds a runtime check verifying that functions
annotated with "returns_nonnull" attribute do in fact return nonnull pointers.
It is based on suggestion by Jakub Jelinek:
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140623/223693.html.
Test Plan: regression test suite
Reviewers: rsmith
Reviewed By: rsmith
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D4849
Modified:
cfe/trunk/docs/UsersManual.rst
cfe/trunk/include/clang/Basic/Sanitizers.def
cfe/trunk/lib/CodeGen/CGCall.cpp
cfe/trunk/test/CodeGen/catch-undef-behavior.c
cfe/trunk/test/Driver/fsanitize.c
Modified: cfe/trunk/docs/UsersManual.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UsersManual.rst?rev=215485&r1=215484&r2=215485&view=diff
==============================================================================
--- cfe/trunk/docs/UsersManual.rst (original)
+++ cfe/trunk/docs/UsersManual.rst Tue Aug 12 19:26:40 2014
@@ -986,6 +986,8 @@ are listed below.
more problems at higher optimization levels.
- ``-fsanitize=return``: In C++, reaching the end of a
value-returning function without returning a value.
+ - ``-fsanitize=returns-nonnull-attribute``: Returning null pointer
+ from a function which is declared to never return null.
- ``-fsanitize=shift``: Shift operators where the amount shifted is
greater or equal to the promoted bit-width of the left hand side
or less than zero, or where the left hand side is negative. For a
Modified: cfe/trunk/include/clang/Basic/Sanitizers.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.def?rev=215485&r1=215484&r2=215485&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Sanitizers.def (original)
+++ cfe/trunk/include/clang/Basic/Sanitizers.def Tue Aug 12 19:26:40 2014
@@ -62,6 +62,7 @@ SANITIZER("integer-divide-by-zero", Inte
SANITIZER("null", Null)
SANITIZER("object-size", ObjectSize)
SANITIZER("return", Return)
+SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute)
SANITIZER("shift", Shift)
SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
SANITIZER("unreachable", Unreachable)
@@ -78,9 +79,9 @@ SANITIZER("dataflow", DataFlow)
// ABI or address space layout implications, and only catch undefined behavior.
SANITIZER_GROUP("undefined", Undefined,
Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
- FloatDivideByZero | Function | IntegerDivideByZero | Null |
- ObjectSize | Return | Shift | SignedIntegerOverflow |
- Unreachable | VLABound | Vptr)
+ FloatDivideByZero | Function | IntegerDivideByZero | Null |
+ ObjectSize | Return | ReturnsNonnullAttribute | Shift |
+ SignedIntegerOverflow | Unreachable | VLABound | Vptr)
// -fsanitize=undefined-trap includes
// all sanitizers included by -fsanitize=undefined, except those that require
@@ -88,9 +89,9 @@ SANITIZER_GROUP("undefined", Undefined,
// -fsanitize-undefined-trap-on-error flag.
SANITIZER_GROUP("undefined-trap", UndefinedTrap,
Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
- FloatDivideByZero | IntegerDivideByZero | Null | ObjectSize |
- Return | Shift | SignedIntegerOverflow | Unreachable |
- VLABound)
+ FloatDivideByZero | IntegerDivideByZero | Null |
+ ObjectSize | Return | ReturnsNonnullAttribute | Shift |
+ SignedIntegerOverflow | Unreachable | VLABound)
SANITIZER_GROUP("integer", Integer,
SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=215485&r1=215484&r2=215485&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Aug 12 19:26:40 2014
@@ -1998,7 +1998,24 @@ void CodeGenFunction::EmitFunctionEpilog
llvm_unreachable("Invalid ABI kind for return argument");
}
- llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) : Builder.CreateRetVoid();
+ llvm::Instruction *Ret;
+ if (RV) {
+ if (SanOpts->ReturnsNonnullAttribute &&
+ CurGD.getDecl()->hasAttr<ReturnsNonNullAttr>()) {
+ SanitizerScope SanScope(this);
+ llvm::Value *Cond =
+ Builder.CreateICmpNE(RV, llvm::Constant::getNullValue(RV->getType()));
+ llvm::Constant *StaticData[] = {
+ EmitCheckSourceLocation(EndLoc)
+ };
+ EmitCheck(Cond, "nonnull_return", StaticData, ArrayRef<llvm::Value *>(),
+ CRK_Recoverable);
+ }
+ Ret = Builder.CreateRet(RV);
+ } else {
+ Ret = Builder.CreateRetVoid();
+ }
+
if (!RetDbgLoc.isUnknown())
Ret->setDebugLoc(RetDbgLoc);
}
Modified: cfe/trunk/test/CodeGen/catch-undef-behavior.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/catch-undef-behavior.c?rev=215485&r1=215484&r2=215485&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/catch-undef-behavior.c (original)
+++ cfe/trunk/test/CodeGen/catch-undef-behavior.c Tue Aug 12 19:26:40 2014
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -fsanitize-undefined-trap-on-error -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-TRAP
+// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -fsanitize-undefined-trap-on-error -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-TRAP
// RUN: %clang_cc1 -fsanitize=null -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-NULL
// RUN: %clang_cc1 -fsanitize=signed-integer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-OVERFLOW
@@ -432,6 +432,20 @@ _Bool sour_bool(_Bool *p) {
return *p;
}
+// CHECK-LABEL: @ret_nonnull
+__attribute__((returns_nonnull))
+int *ret_nonnull(int *a) {
+ // CHECK: [[OK:%.*]] = icmp ne i32* {{.*}}, null
+ // CHECK: br i1 [[OK]]
+ // CHECK: call void @__ubsan_handle_nonnull_return
+
+ // CHECK-TRAP: [[OK:%.*]] = icmp ne i32* {{.*}}, null
+ // CHECK-TRAP: br i1 [[OK]]
+ // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]]
+ // CHECK-TRAP: unreachable
+ return a;
+}
+
// CHECK: ![[WEIGHT_MD]] = metadata !{metadata !"branch_weights", i32 1048575, i32 1}
// CHECK-TRAP: attributes [[NR_NUW]] = { noreturn nounwind }
Modified: cfe/trunk/test/Driver/fsanitize.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=215485&r1=215484&r2=215485&view=diff
==============================================================================
--- cfe/trunk/test/Driver/fsanitize.c (original)
+++ cfe/trunk/test/Driver/fsanitize.c Tue Aug 12 19:26:40 2014
@@ -1,13 +1,13 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
// RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
-// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool),?){14}"}}
+// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute),?){15}"}}
// CHECK-UNDEFINED-TRAP: "-fsanitize-undefined-trap-on-error"
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED
-// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool),?){16}"}}
+// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute),?){17}"}}
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN
-// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool),?){15}"}}
+// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute),?){16}"}}
// RUN: %clang -target x86_64-linux-gnu -fsanitize=integer %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INTEGER
// CHECK-INTEGER: "-fsanitize={{((signed-integer-overflow|unsigned-integer-overflow|integer-divide-by-zero|shift),?){4}"}}
@@ -16,7 +16,7 @@
// CHECK-BOUNDS: "-fsanitize={{((array-bounds|local-bounds),?){2}"}}
// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-sanitize=thread -fno-sanitize=float-cast-overflow,vptr,bool,enum %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED
-// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift|unreachable|return|vla-bound|alignment|null|object-size|array-bounds),?){12}"}}
+// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift|unreachable|return|vla-bound|alignment|null|object-size|array-bounds|returns-nonnull-attribute),?){13}"}}
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP-ON-ERROR-UNDEF
// CHECK-UNDEFINED-TRAP-ON-ERROR-UNDEF: '-fsanitize=undefined' not allowed with '-fsanitize-undefined-trap-on-error'
More information about the cfe-commits
mailing list