@@ -630,6 +630,83 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
630
630
}
631
631
}
632
632
633
+ // / Determine whether this expression refers to a flexible array member in a
634
+ // / struct. We disable array bounds checks for such members.
635
+ static bool isFlexibleArrayMemberExpr (const Expr *E) {
636
+ // For compatibility with existing code, we treat arrays of length 0 or
637
+ // 1 as flexible array members.
638
+ const ArrayType *AT = E->getType ()->castAsArrayTypeUnsafe ();
639
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
640
+ if (CAT->getSize ().ugt (1 ))
641
+ return false ;
642
+ } else if (!isa<IncompleteArrayType>(AT))
643
+ return false ;
644
+
645
+ E = E->IgnoreParens ();
646
+
647
+ // A flexible array member must be the last member in the class.
648
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
649
+ // FIXME: If the base type of the member expr is not FD->getParent(),
650
+ // this should not be treated as a flexible array member access.
651
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl ())) {
652
+ RecordDecl::field_iterator FI (
653
+ DeclContext::decl_iterator (const_cast <FieldDecl *>(FD)));
654
+ return ++FI == FD->getParent ()->field_end ();
655
+ }
656
+ }
657
+
658
+ return false ;
659
+ }
660
+
661
+ // / If Base is known to point to the start of an array, return the length of
662
+ // / that array. Return 0 if the length cannot be determined.
663
+ llvm::Value *getArrayIndexingBound (CodeGenFunction &CGF, const Expr *Base,
664
+ QualType &IndexedType) {
665
+ // For the vector indexing extension, the bound is the number of elements.
666
+ if (const VectorType *VT = Base->getType ()->getAs <VectorType>()) {
667
+ IndexedType = Base->getType ();
668
+ return CGF.Builder .getInt32 (VT->getNumElements ());
669
+ }
670
+
671
+ Base = Base->IgnoreParens ();
672
+
673
+ if (const CastExpr *CE = dyn_cast<CastExpr>(Base)) {
674
+ if (CE->getCastKind () == CK_ArrayToPointerDecay &&
675
+ !isFlexibleArrayMemberExpr (CE->getSubExpr ())) {
676
+ IndexedType = CE->getSubExpr ()->getType ();
677
+ const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe ();
678
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
679
+ return CGF.Builder .getInt (CAT->getSize ());
680
+ else if (const VariableArrayType *VAT = cast<VariableArrayType>(AT))
681
+ return CGF.getVLASize (VAT).first ;
682
+ }
683
+ }
684
+
685
+ return 0 ;
686
+ }
687
+
688
+ void CodeGenFunction::EmitBoundsCheck (const Expr *E, const Expr *Base,
689
+ llvm::Value *Index, QualType IndexType,
690
+ bool Accessed) {
691
+ QualType IndexedType;
692
+ llvm::Value *Bound = getArrayIndexingBound (*this , Base, IndexedType);
693
+ if (!Bound)
694
+ return ;
695
+
696
+ bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType ();
697
+ llvm::Value *IndexVal = Builder.CreateIntCast (Index, SizeTy, IndexSigned);
698
+ llvm::Value *BoundVal = Builder.CreateIntCast (Bound, SizeTy, false );
699
+
700
+ llvm::Constant *StaticData[] = {
701
+ EmitCheckSourceLocation (E->getExprLoc ()),
702
+ EmitCheckTypeDescriptor (IndexedType),
703
+ EmitCheckTypeDescriptor (IndexType)
704
+ };
705
+ llvm::Value *Check = Accessed ? Builder.CreateICmpULT (IndexVal, BoundVal)
706
+ : Builder.CreateICmpULE (IndexVal, BoundVal);
707
+ EmitCheck (Check, " out_of_bounds" , StaticData, Index, CRK_Recoverable);
708
+ }
709
+
633
710
634
711
CodeGenFunction::ComplexPairTy CodeGenFunction::
635
712
EmitComplexPrePostIncDec (const UnaryOperator *E, LValue LV,
@@ -705,7 +782,11 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
705
782
}
706
783
707
784
LValue CodeGenFunction::EmitCheckedLValue (const Expr *E, TypeCheckKind TCK) {
708
- LValue LV = EmitLValue (E);
785
+ LValue LV;
786
+ if (SanOpts->Bounds && isa<ArraySubscriptExpr>(E))
787
+ LV = EmitArraySubscriptExpr (cast<ArraySubscriptExpr>(E), /* Accessed*/ true );
788
+ else
789
+ LV = EmitLValue (E);
709
790
if (!isa<DeclRefExpr>(E) && !LV.isBitField () && LV.isSimple ())
710
791
EmitTypeCheck (TCK, E->getExprLoc (), LV.getAddress (),
711
792
E->getType (), LV.getAlignment ());
@@ -2121,12 +2202,16 @@ static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
2121
2202
return SubExpr;
2122
2203
}
2123
2204
2124
- LValue CodeGenFunction::EmitArraySubscriptExpr (const ArraySubscriptExpr *E) {
2205
+ LValue CodeGenFunction::EmitArraySubscriptExpr (const ArraySubscriptExpr *E,
2206
+ bool Accessed) {
2125
2207
// The index must always be an integer, which is not an aggregate. Emit it.
2126
2208
llvm::Value *Idx = EmitScalarExpr (E->getIdx ());
2127
2209
QualType IdxTy = E->getIdx ()->getType ();
2128
2210
bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType ();
2129
2211
2212
+ if (SanOpts->Bounds )
2213
+ EmitBoundsCheck (E, E->getBase (), Idx, IdxTy, Accessed);
2214
+
2130
2215
// If the base is a vector type, then we are forming a vector element lvalue
2131
2216
// with this subscript.
2132
2217
if (E->getBase ()->getType ()->isVectorType ()) {
@@ -2187,7 +2272,13 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
2187
2272
// "gep x, i" here. Emit one "gep A, 0, i".
2188
2273
assert (Array->getType ()->isArrayType () &&
2189
2274
" Array to pointer decay must have array source type!" );
2190
- LValue ArrayLV = EmitLValue (Array);
2275
+ LValue ArrayLV;
2276
+ // For simple multidimensional array indexing, set the 'accessed' flag for
2277
+ // better bounds-checking of the base expression.
2278
+ if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(Array))
2279
+ ArrayLV = EmitArraySubscriptExpr (ASE, /* Accessed*/ true );
2280
+ else
2281
+ ArrayLV = EmitLValue (Array);
2191
2282
llvm::Value *ArrayPtr = ArrayLV.getAddress ();
2192
2283
llvm::Value *Zero = llvm::ConstantInt::get (Int32Ty, 0 );
2193
2284
llvm::Value *Args[] = { Zero, Idx };
0 commit comments