forked from OSchip/llvm-project
[clang][CodeGen][UBSan] VLA size checking for unsigned integer parameter
The code generation for the UBSan VLA size check was qualified by a con- dition that the parameter must be a signed integer, however the C spec does not make any distinction that only signed integer parameters can be used to declare a VLA, only qualifying that it must be greater than zero if it is not a constant. Reviewed By: rjmccall Differential Revision: https://reviews.llvm.org/D116048
This commit is contained in:
parent
b7f298f174
commit
b2715660ed
|
@ -2247,32 +2247,36 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
|
||||||
|
|
||||||
// Unknown size indication requires no size computation.
|
// Unknown size indication requires no size computation.
|
||||||
// Otherwise, evaluate and record it.
|
// Otherwise, evaluate and record it.
|
||||||
if (const Expr *size = vat->getSizeExpr()) {
|
if (const Expr *sizeExpr = vat->getSizeExpr()) {
|
||||||
// It's possible that we might have emitted this already,
|
// It's possible that we might have emitted this already,
|
||||||
// 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[sizeExpr];
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
llvm::Value *Size = EmitScalarExpr(size);
|
llvm::Value *size = EmitScalarExpr(sizeExpr);
|
||||||
|
|
||||||
// C11 6.7.6.2p5:
|
// C11 6.7.6.2p5:
|
||||||
// If the size is an expression that is not an integer constant
|
// If the size is an expression that is not an integer constant
|
||||||
// expression [...] each time it is evaluated it shall have a value
|
// expression [...] each time it is evaluated it shall have a value
|
||||||
// greater than zero.
|
// greater than zero.
|
||||||
if (SanOpts.has(SanitizerKind::VLABound) &&
|
if (SanOpts.has(SanitizerKind::VLABound)) {
|
||||||
size->getType()->isSignedIntegerType()) {
|
|
||||||
SanitizerScope SanScope(this);
|
SanitizerScope SanScope(this);
|
||||||
llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType());
|
llvm::Value *Zero = llvm::Constant::getNullValue(size->getType());
|
||||||
|
clang::QualType SEType = sizeExpr->getType();
|
||||||
|
llvm::Value *CheckCondition =
|
||||||
|
SEType->isSignedIntegerType()
|
||||||
|
? Builder.CreateICmpSGT(size, Zero)
|
||||||
|
: Builder.CreateICmpUGT(size, Zero);
|
||||||
llvm::Constant *StaticArgs[] = {
|
llvm::Constant *StaticArgs[] = {
|
||||||
EmitCheckSourceLocation(size->getBeginLoc()),
|
EmitCheckSourceLocation(sizeExpr->getBeginLoc()),
|
||||||
EmitCheckTypeDescriptor(size->getType())};
|
EmitCheckTypeDescriptor(SEType)};
|
||||||
EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero),
|
EmitCheck(std::make_pair(CheckCondition, SanitizerKind::VLABound),
|
||||||
SanitizerKind::VLABound),
|
SanitizerHandler::VLABoundNotPositive, StaticArgs, size);
|
||||||
SanitizerHandler::VLABoundNotPositive, 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(Size, SizeTy, /*signed*/ false);
|
// FIXME: What about when size's type is larger than size_t?
|
||||||
|
entry = Builder.CreateIntCast(size, SizeTy, /*signed*/ false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type = vat->getElementType();
|
type = vat->getElementType();
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
// CHECK-UBSAN: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i8 2, i8 3 }
|
// CHECK-UBSAN: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i8 2, i8 3 }
|
||||||
// CHECK-UBSAN: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} }
|
// CHECK-UBSAN: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} }
|
||||||
// CHECK-UBSAN: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} }
|
// CHECK-UBSAN: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} }
|
||||||
|
// CHECK-UBSAN: @[[LINE_1000:.*]] = {{.*}}, i32 1000, i32 11 {{.*}} @{{.*}} }
|
||||||
// CHECK-UBSAN: @[[FP16:.*]] = private unnamed_addr constant { i16, i16, [9 x i8] } { i16 1, i16 16, [9 x i8] c"'__fp16'\00" }
|
// CHECK-UBSAN: @[[FP16:.*]] = private unnamed_addr constant { i16, i16, [9 x i8] } { i16 1, i16 16, [9 x i8] c"'__fp16'\00" }
|
||||||
// CHECK-UBSAN: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 10 {{.*}} @{{.*}} }
|
// CHECK-UBSAN: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 10 {{.*}} @{{.*}} }
|
||||||
// CHECK-UBSAN: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 10 {{.*}} @{{.*}} }
|
// CHECK-UBSAN: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 10 {{.*}} @{{.*}} }
|
||||||
|
@ -186,6 +187,16 @@ void vla_bound(int n) {
|
||||||
int arr[n * 3];
|
int arr[n * 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK-UBSAN-LABEL: @vla_bound_unsigned
|
||||||
|
void vla_bound_unsigned(unsigned int n) {
|
||||||
|
// CHECK-UBSAN: icmp ugt i32 %[[PARAM:.*]], 0
|
||||||
|
//
|
||||||
|
// CHECK-UBSAN: %[[ARG:.*]] = zext i32 %[[PARAM]] to i64
|
||||||
|
// CHECK-UBSAN-NEXT: call void @__ubsan_handle_vla_bound_not_positive(i8* bitcast ({{.*}} @[[LINE_1000]] to i8*), i64 %[[ARG]])
|
||||||
|
#line 1000
|
||||||
|
int arr[n * 3];
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK-UBSAN-LABEL: @int_float_no_overflow
|
// CHECK-UBSAN-LABEL: @int_float_no_overflow
|
||||||
float int_float_no_overflow(__int128 n) {
|
float int_float_no_overflow(__int128 n) {
|
||||||
// CHECK-UBSAN-NOT: call void @__ubsan_handle
|
// CHECK-UBSAN-NOT: call void @__ubsan_handle
|
||||||
|
|
Loading…
Reference in New Issue