Skip to content

Commit 033a1ce

Browse files
committed
handle VLAs
1 parent 1c11e60 commit 033a1ce

File tree

2 files changed

+36
-16
lines changed

2 files changed

+36
-16
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4608,6 +4608,11 @@ void CodeGenFunction::EmitArrayBoundsConstraints(const ArraySubscriptExpr *E,
46084608
if (SanOpts.has(SanitizerKind::ArrayBounds))
46094609
return;
46104610

4611+
// Use the provided IndexVal to avoid duplicating side effects.
4612+
// The caller has already emitted the index expression once.
4613+
if (!IndexVal)
4614+
return;
4615+
46114616
const Expr *Base = E->getBase();
46124617
const Expr *Idx = E->getIdx();
46134618
QualType BaseType = Base->getType();
@@ -4618,19 +4623,28 @@ void CodeGenFunction::EmitArrayBoundsConstraints(const ArraySubscriptExpr *E,
46184623
}
46194624
}
46204625

4621-
// For now: only handle constant array types.
4626+
// Handle both constant arrays and VLAs (variable-length arrays.)
46224627
const ConstantArrayType *CAT = getContext().getAsConstantArrayType(BaseType);
4623-
if (!CAT)
4624-
return;
4628+
llvm::Value *VLASize = nullptr;
46254629

4626-
llvm::APInt ArraySize = CAT->getSize();
4630+
if (!CAT) {
4631+
if (const VariableArrayType *VAT =
4632+
getContext().getAsVariableArrayType(BaseType))
4633+
VLASize = getVLASize(VAT).NumElts;
4634+
else
4635+
return; // Not a constant or VLA.
4636+
}
4637+
4638+
llvm::APInt ArraySize;
4639+
if (CAT)
4640+
ArraySize = CAT->getSize();
46274641

46284642
// Don't generate assumes for flexible array member pattern.
46294643
// Size-1 arrays: "struct { int len; char data[1]; }" (pre-C99 idiom.)
46304644
// Zero-length arrays: "struct { int len; char data[0]; }" (GCC extension
46314645
// https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html)
46324646
// Both patterns use arrays as placeholders for variable-length data.
4633-
if (ArraySize == 0 || ArraySize == 1) {
4647+
if (CAT && (ArraySize == 0 || ArraySize == 1)) {
46344648
if (const auto *ME = dyn_cast<MemberExpr>(Base->IgnoreParenImpCasts())) {
46354649
if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
46364650
const RecordDecl *RD = FD->getParent();
@@ -4649,15 +4663,18 @@ void CodeGenFunction::EmitArrayBoundsConstraints(const ArraySubscriptExpr *E,
46494663

46504664
QualType IdxType = Idx->getType();
46514665
llvm::Type *IndexType = ConvertType(IdxType);
4652-
llvm::Value *Zero = llvm::ConstantInt::get(IndexType, 0);
4653-
4654-
uint64_t ArraySizeValue = ArraySize.getLimitedValue();
4655-
llvm::Value *ArraySizeVal = llvm::ConstantInt::get(IndexType, ArraySizeValue);
4666+
llvm::Value *ArraySizeVal;
46564667

4657-
// Use the provided IndexVal to avoid duplicating side effects.
4658-
// The caller has already emitted the index expression once.
4659-
if (!IndexVal)
4660-
return;
4668+
if (CAT)
4669+
// Constant array: use compile-time size.
4670+
ArraySizeVal =
4671+
llvm::ConstantInt::get(IndexType, ArraySize.getLimitedValue());
4672+
else
4673+
// VLA: use runtime size.
4674+
ArraySizeVal =
4675+
VLASize->getType() == IndexType
4676+
? VLASize
4677+
: Builder.CreateIntCast(VLASize, IndexType, false, "vla.size.cast");
46614678

46624679
// Ensure index value has the same type as our constants.
46634680
if (IndexVal->getType() != IndexType) {
@@ -4672,6 +4689,7 @@ void CodeGenFunction::EmitArrayBoundsConstraints(const ArraySubscriptExpr *E,
46724689
// array."
46734690
if (IdxType->isSignedIntegerOrEnumerationType()) {
46744691
// For signed indices: index >= 0 && index < size.
4692+
llvm::Value *Zero = llvm::ConstantInt::get(IndexType, 0);
46754693
llvm::Value *LowerBound =
46764694
Builder.CreateICmpSGE(IndexVal, Zero, "idx.ge.zero");
46774695
llvm::Value *UpperBound =

clang/test/CodeGen/array-bounds-constraints-safety.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ int test_pointer_parameter(int *arr, int i) {
5555
}
5656

5757
// CHECK-LABEL: define {{.*}} @test_vla
58+
void init_vla(int *arr, int n);
59+
5860
int test_vla(int n, int i) {
5961
int arr[n]; // Variable-length array.
60-
// CHECK-NOT: call void @llvm.assume
61-
// VLAs should NOT generate bounds constraints
62-
// because the size is dynamic.
62+
init_vla(arr, n); // Initialize to avoid UB.
63+
// CHECK: call void @llvm.assume
64+
// For VLAs, generate bounds constraints using the runtime size: 0 <= i < n.
6365
return arr[i];
6466
}
6567

0 commit comments

Comments
 (0)