[PATCH] D116048: [clang][CodeGen][UBSan] VLA size checking for unsigned integer parameter

Adam Magier via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 20 09:14:53 PST 2021


AdamMagierFOSS created this revision.
AdamMagierFOSS added reviewers: rjmccall, rsmith.
AdamMagierFOSS requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D116048

Files:
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/test/CodeGen/catch-undef-behavior.c


Index: clang/test/CodeGen/catch-undef-behavior.c
===================================================================
--- clang/test/CodeGen/catch-undef-behavior.c
+++ clang/test/CodeGen/catch-undef-behavior.c
@@ -17,6 +17,7 @@
 // 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_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: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 10 {{.*}} @{{.*}} }
 // CHECK-UBSAN: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 10 {{.*}} @{{.*}} }
@@ -186,6 +187,16 @@
   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
 float int_float_no_overflow(__int128 n) {
   // CHECK-UBSAN-NOT: call void @__ubsan_handle
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2244,32 +2244,35 @@
 
       // Unknown size indication requires no size computation.
       // 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,
         // e.g. with a typedef and a pointer to it.
-        llvm::Value *&entry = VLASizeMap[size];
-        if (!entry) {
-          llvm::Value *Size = EmitScalarExpr(size);
+        llvm::Value *&MapEntry = VLASizeMap[SizeExpr];
+        if (!MapEntry) {
+          llvm::Value *Size = EmitScalarExpr(SizeExpr);
+          clang::QualType SEType = SizeExpr->getType();
 
           // 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 (SanOpts.has(SanitizerKind::VLABound) &&
-              size->getType()->isSignedIntegerType()) {
+          if (SanOpts.has(SanitizerKind::VLABound) && SEType->isIntegerType()) {
             SanitizerScope SanScope(this);
             llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType());
+            llvm::Value *CheckCondition =
+                SEType->isSignedIntegerType()
+                    ? Builder.CreateICmpSGT(Size, Zero)
+                    : Builder.CreateICmpUGT(Size, Zero);
             llvm::Constant *StaticArgs[] = {
-                EmitCheckSourceLocation(size->getBeginLoc()),
-                EmitCheckTypeDescriptor(size->getType())};
-            EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero),
-                                     SanitizerKind::VLABound),
+                EmitCheckSourceLocation(SizeExpr->getBeginLoc()),
+                EmitCheckTypeDescriptor(SEType)};
+            EmitCheck(std::make_pair(CheckCondition, SanitizerKind::VLABound),
                       SanitizerHandler::VLABoundNotPositive, StaticArgs, Size);
           }
 
           // Always zexting here would be wrong if it weren't
           // undefined behavior to have a negative bound.
-          entry = Builder.CreateIntCast(Size, SizeTy, /*signed*/ false);
+          MapEntry = Builder.CreateIntCast(Size, SizeTy, /*signed*/ false);
         }
       }
       type = vat->getElementType();


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D116048.395465.patch
Type: text/x-patch
Size: 3960 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20211220/9243b379/attachment.bin>


More information about the cfe-commits mailing list