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' _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
