forked from OSchip/llvm-project
-fcatch-undefined-behavior: catch a VLA bound which evalutes to a non-positive value.
llvm-svn: 165583
This commit is contained in:
parent
22cc16462e
commit
481652b3e3
|
@ -1043,6 +1043,7 @@ CodeGenFunction::getVLASize(const VariableArrayType *type) {
|
||||||
numElements = vlaSize;
|
numElements = vlaSize;
|
||||||
} else {
|
} else {
|
||||||
// It's undefined behavior if this wraps around, so mark it that way.
|
// It's undefined behavior if this wraps around, so mark it that way.
|
||||||
|
// FIXME: Teach -fcatch-undefined-behavior to trap this.
|
||||||
numElements = Builder.CreateNUWMul(numElements, vlaSize);
|
numElements = Builder.CreateNUWMul(numElements, vlaSize);
|
||||||
}
|
}
|
||||||
} while ((type = getContext().getAsVariableArrayType(elementType)));
|
} while ((type = getContext().getAsVariableArrayType(elementType)));
|
||||||
|
@ -1120,9 +1121,25 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
|
||||||
// e.g. with a typedef and a pointer to it.
|
// e.g. with a typedef and a pointer to it.
|
||||||
llvm::Value *&entry = VLASizeMap[size];
|
llvm::Value *&entry = VLASizeMap[size];
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
|
llvm::Value *Size = EmitScalarExpr(size);
|
||||||
|
|
||||||
|
// C11 6.7.6.2p5:
|
||||||
|
// If the size is an expression that is not an integer constant
|
||||||
|
// expression [...] each time it is evaluated it shall have a value
|
||||||
|
// greater than zero.
|
||||||
|
if (CatchUndefined && size->getType()->isSignedIntegerType()) {
|
||||||
|
llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType());
|
||||||
|
llvm::Constant *StaticArgs[] = {
|
||||||
|
EmitCheckSourceLocation(size->getLocStart()),
|
||||||
|
EmitCheckTypeDescriptor(size->getType())
|
||||||
|
};
|
||||||
|
EmitCheck(Builder.CreateICmpSGT(Size, Zero),
|
||||||
|
"vla_bound_not_positive", StaticArgs, Size);
|
||||||
|
}
|
||||||
|
|
||||||
// Always zexting here would be wrong if it weren't
|
// Always zexting here would be wrong if it weren't
|
||||||
// undefined behavior to have a negative bound.
|
// undefined behavior to have a negative bound.
|
||||||
entry = Builder.CreateIntCast(EmitScalarExpr(size), SizeTy,
|
entry = Builder.CreateIntCast(Size, SizeTy,
|
||||||
/*signed*/ false);
|
/*signed*/ false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
// CHECK: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i64 4, i8 3 }
|
// CHECK: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i64 4, i8 3 }
|
||||||
// CHECK: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} }
|
// CHECK: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} }
|
||||||
|
// CHECK: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} }
|
||||||
|
|
||||||
// PR6805
|
// PR6805
|
||||||
// CHECK: @foo
|
// CHECK: @foo
|
||||||
|
@ -130,3 +131,13 @@ int no_return() {
|
||||||
// CHECK-NOT: unreachable
|
// CHECK-NOT: unreachable
|
||||||
// CHECK: ret i32
|
// CHECK: ret i32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK: @vla_bound
|
||||||
|
void vla_bound(int n) {
|
||||||
|
// CHECK: icmp sgt i32 %[[PARAM:.*]], 0
|
||||||
|
//
|
||||||
|
// CHECK: %[[ARG:.*]] = zext i32 %[[PARAM]] to i64
|
||||||
|
// CHECK-NEXT: call void @__ubsan_handle_vla_bound_not_positive(i8* bitcast ({{.*}} @[[LINE_900]] to i8*), i64 %[[ARG]]) noreturn nounwind
|
||||||
|
#line 900
|
||||||
|
int arr[n * 3];
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue