]> granicus.if.org Git - clang/commitdiff
-fcatch-undefined-behavior: catch a VLA bound which evalutes to a non-positive value.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 10 Oct 2012 01:11:12 +0000 (01:11 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 10 Oct 2012 01:11:12 +0000 (01:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165583 91177308-0d34-0410-b5e6-96231b3b80d8

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

index d7fcf9f8b21521f00599b96087938b9508c1eb5a..9c0b1aa54962743e61ed13b8d79c04e49651658a 100644 (file)
@@ -1043,6 +1043,7 @@ CodeGenFunction::getVLASize(const VariableArrayType *type) {
       numElements = vlaSize;
     } else {
       // 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);
     }
   } while ((type = getContext().getAsVariableArrayType(elementType)));
@@ -1120,9 +1121,25 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
         // e.g. with a typedef and a pointer to it.
         llvm::Value *&entry = VLASizeMap[size];
         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
           // undefined behavior to have a negative bound.
-          entry = Builder.CreateIntCast(EmitScalarExpr(size), SizeTy,
+          entry = Builder.CreateIntCast(Size, SizeTy,
                                         /*signed*/ false);
         }
       }
index 2fe61ea6758916b810d15a3c0cab338c47496eb6..e8b5cbcd56f1d2ab038e9b0e3837486edd4eaf92 100644 (file)
@@ -15,6 +15,7 @@
 
 // CHECK: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i64 4, i8 3 }
 // CHECK: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} }
+// CHECK: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} }
 
 // PR6805
 // CHECK: @foo
@@ -130,3 +131,13 @@ int no_return() {
   // CHECK-NOT: unreachable
   // 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];
+}