Awesome!
On 13 December 2012 02:11, Richard Smith <[email protected]> wrote: > Author: rsmith > Date: Thu Dec 13 01:11:50 2012 > New Revision: 170108 > > URL: http://llvm.org/viewvc/llvm-project?rev=170108&view=rev > Log: > ubsan: Add -fsanitize=bool and -fsanitize=enum, which check for loads of > bit-patterns which are not valid values for enumerated or boolean types. > These checks are the ubsan analogue of !range metadata. > > Modified: > cfe/trunk/docs/UsersManual.rst > cfe/trunk/include/clang/Basic/Sanitizers.def > cfe/trunk/lib/CodeGen/CGExpr.cpp > cfe/trunk/test/CodeGen/catch-undef-behavior.c > cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp > 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=170108&r1=170107&r2=170108&view=diff > ============================================================================== > --- cfe/trunk/docs/UsersManual.rst (original) > +++ cfe/trunk/docs/UsersManual.rst Thu Dec 13 01:11:50 2012 > @@ -834,8 +834,13 @@ > > - ``-fsanitize=alignment``: Use of a misaligned pointer or creation > of a misaligned reference. > + - ``-fsanitize=bool``: Load of a ``bool`` value which is neither > + ``true`` nor ``false``. > - ``-fsanitize=bounds``: Out of bounds array indexing, in cases > where the array bound can be statically determined. > + - ``-fsanitize=enum``: Load of a value of an enumerated type which > + is not in the range of representable values for that enumerated > + type. > - ``-fsanitize=float-cast-overflow``: Conversion to, from, or > between floating-point types which would overflow the > destination. > > Modified: cfe/trunk/include/clang/Basic/Sanitizers.def > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.def?rev=170108&r1=170107&r2=170108&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Basic/Sanitizers.def (original) > +++ cfe/trunk/include/clang/Basic/Sanitizers.def Thu Dec 13 01:11:50 2012 > @@ -56,7 +56,9 @@ > > // UndefinedBehaviorSanitizer > SANITIZER("alignment", Alignment) > +SANITIZER("bool", Bool) > SANITIZER("bounds", Bounds) > +SANITIZER("enum", Enum) > SANITIZER("float-cast-overflow", FloatCastOverflow) > SANITIZER("float-divide-by-zero", FloatDivideByZero) > SANITIZER("integer-divide-by-zero", IntegerDivideByZero) > @@ -76,9 +78,10 @@ > // include all the sanitizers which have low overhead, no ABI or address > space > // layout implications, and only catch undefined behavior. > SANITIZER_GROUP("undefined", Undefined, > - Alignment | Bounds | FloatCastOverflow | FloatDivideByZero | > - IntegerDivideByZero | Null | ObjectSize | Return | Shift | > - SignedIntegerOverflow | Unreachable | VLABound | Vptr) > + Alignment | Bool | Bounds | Enum | FloatCastOverflow | > + FloatDivideByZero | IntegerDivideByZero | Null | ObjectSize | > + Return | Shift | SignedIntegerOverflow | Unreachable | > + VLABound | Vptr) > > SANITIZER_GROUP("integer", Integer, > SignedIntegerOverflow | UnsignedIntegerOverflow | Shift | > > Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=170108&r1=170107&r2=170108&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Dec 13 01:11:50 2012 > @@ -924,23 +924,22 @@ > return false; > } > > -llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) { > +static bool getRangeForType(CodeGenFunction &CGF, QualType Ty, > + llvm::APInt &Min, llvm::APInt &End, > + bool StrictEnums) { > const EnumType *ET = Ty->getAs<EnumType>(); > - bool IsRegularCPlusPlusEnum = (getLangOpts().CPlusPlus && ET && > - CGM.getCodeGenOpts().StrictEnums && > - !ET->getDecl()->isFixed()); > + bool IsRegularCPlusPlusEnum = CGF.getLangOpts().CPlusPlus && StrictEnums && > + ET && !ET->getDecl()->isFixed(); > bool IsBool = hasBooleanRepresentation(Ty); > if (!IsBool && !IsRegularCPlusPlusEnum) > - return NULL; > + return false; > > - llvm::APInt Min; > - llvm::APInt End; > if (IsBool) { > - Min = llvm::APInt(getContext().getTypeSize(Ty), 0); > - End = llvm::APInt(getContext().getTypeSize(Ty), 2); > + Min = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0); > + End = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2); > } else { > const EnumDecl *ED = ET->getDecl(); > - llvm::Type *LTy = ConvertTypeForMem(ED->getIntegerType()); > + llvm::Type *LTy = CGF.ConvertTypeForMem(ED->getIntegerType()); > unsigned Bitwidth = LTy->getScalarSizeInBits(); > unsigned NumNegativeBits = ED->getNumNegativeBits(); > unsigned NumPositiveBits = ED->getNumPositiveBits(); > @@ -956,6 +955,14 @@ > Min = llvm::APInt(Bitwidth, 0); > } > } > + return true; > +} > + > +llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) { > + llvm::APInt Min, End; > + if (!getRangeForType(*this, Ty, Min, End, > + CGM.getCodeGenOpts().StrictEnums)) > + return 0; > > llvm::MDBuilder MDHelper(getLLVMContext()); > return MDHelper.createRange(Min, End); > @@ -1014,7 +1021,27 @@ > if (Ty->isAtomicType()) > Load->setAtomic(llvm::SequentiallyConsistent); > > - if (CGM.getCodeGenOpts().OptimizationLevel > 0) > + if ((getLangOpts().SanitizeBool && hasBooleanRepresentation(Ty)) || > + (getLangOpts().SanitizeEnum && Ty->getAs<EnumType>())) { > + llvm::APInt Min, End; > + if (getRangeForType(*this, Ty, Min, End, true)) { > + --End; > + llvm::Value *Check; > + if (!Min) > + Check = Builder.CreateICmpULE( > + Load, llvm::ConstantInt::get(getLLVMContext(), End)); > + else { > + llvm::Value *Upper = Builder.CreateICmpSLE( > + Load, llvm::ConstantInt::get(getLLVMContext(), End)); > + llvm::Value *Lower = Builder.CreateICmpSGE( > + Load, llvm::ConstantInt::get(getLLVMContext(), Min)); > + Check = Builder.CreateAnd(Upper, Lower); > + } > + // FIXME: Provide a SourceLocation. > + EmitCheck(Check, "load_invalid_value", EmitCheckTypeDescriptor(Ty), > + EmitCheckValue(Load), CRK_Recoverable); > + } > + } else if (CGM.getCodeGenOpts().OptimizationLevel > 0) > if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty)) > Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo); > > > 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=170108&r1=170107&r2=170108&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGen/catch-undef-behavior.c (original) > +++ cfe/trunk/test/CodeGen/catch-undef-behavior.c Thu Dec 13 01:11:50 2012 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 > -fsanitize=alignment,null,object-size,shift,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero > -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s > +// 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=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 > > @@ -246,3 +246,11 @@ > // CHECK: } > // CHECK-OVERFLOW: } > } > + > +// CHECK: @sour_bool > +_Bool sour_bool(_Bool *p) { > + // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 > + // CHECK: br i1 %[[OK]] > + // CHECK: call void @__ubsan_handle_load_invalid_value_abort(i8* bitcast > ({{.*}}), i64 {{.*}}) > + return *p; > +} > > Modified: cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp?rev=170108&r1=170107&r2=170108&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp Thu Dec 13 01:11:50 > 2012 > @@ -1,4 +1,4 @@ > -// RUN: %clang_cc1 > -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 > -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s > +// RUN: %clang_cc1 > -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,bool,enum > -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s > > // CHECK: @_Z17reference_binding > void reference_binding(int *p) { > @@ -136,3 +136,36 @@ > // CHECK: call void @__ubsan_handle_missing_return(i8* bitcast > ({{.*}}* @{{.*}} to i8*)) noreturn nounwind > // CHECK-NEXT: unreachable > } > + > +// CHECK: @_Z9sour_bool > +bool sour_bool(bool *p) { > + // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 > + // CHECK: br i1 %[[OK]] > + // CHECK: call void @__ubsan_handle_load_invalid_value_abort(i8* bitcast > ({{.*}}), i64 {{.*}}) > + return *p; > +} > + > +enum E1 { e1a = 0, e1b = 127 } e1; > +enum E2 { e2a = -1, e2b = 64 } e2; > +enum E3 { e3a = (1u << 31) - 1 } e3; > + > +// CHECK: @_Z14bad_enum_value > +int bad_enum_value() { > + // CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127 > + // CHECK: br i1 %[[E1]] > + // CHECK: call void @__ubsan_handle_load_invalid_value_abort( > + int a = e1; > + > + // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127 > + // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128 > + // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]] > + // CHECK: br i1 %[[E2]] > + // CHECK: call void @__ubsan_handle_load_invalid_value_abort( > + int b = e2; > + > + // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647 > + // CHECK: br i1 %[[E3]] > + // CHECK: call void @__ubsan_handle_load_invalid_value_abort( > + int c = e3; > + return a + b + c; > +} > > Modified: cfe/trunk/test/Driver/fsanitize.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=170108&r1=170107&r2=170108&view=diff > ============================================================================== > --- cfe/trunk/test/Driver/fsanitize.c (original) > +++ cfe/trunk/test/Driver/fsanitize.c Thu Dec 13 01:11:50 2012 > @@ -1,13 +1,11 @@ > // RUN: %clang -target x86_64-linux-gnu -fcatch-undefined-behavior %s -### > 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED > // 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|shift|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|bounds|enum|bool),?){15}"}} > > -// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined > -fno-thread-sanitizer -fno-sanitize=float-cast-overflow,vptr %s -### 2>&1 | > FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED > -// CHECK-UNDEFINED: > "-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|bounds),?){13}"}} > -// > // 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}"}} > > -// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined > -fno-thread-sanitizer -fno-sanitize=float-cast-overflow,vptr %s -### 2>&1 | > FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED > +// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined > -fno-thread-sanitizer -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|shift|unreachable|return|vla-bound|alignment|null|object-size|bounds),?){11}"}} > > // RUN: %clang -target x86_64-linux-gnu -fsanitize=address-full %s -### 2>&1 > | FileCheck %s --check-prefix=CHECK-ASAN-FULL > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
