@@ -630,6 +630,83 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
630630 }
631631}
632632
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+
633710
634711CodeGenFunction::ComplexPairTy CodeGenFunction::
635712EmitComplexPrePostIncDec (const UnaryOperator *E, LValue LV,
@@ -705,7 +782,11 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
705782}
706783
707784LValue 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);
709790 if (!isa<DeclRefExpr>(E) && !LV.isBitField () && LV.isSimple ())
710791 EmitTypeCheck (TCK, E->getExprLoc (), LV.getAddress (),
711792 E->getType (), LV.getAlignment ());
@@ -2121,12 +2202,16 @@ static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
21212202 return SubExpr;
21222203}
21232204
2124- LValue CodeGenFunction::EmitArraySubscriptExpr (const ArraySubscriptExpr *E) {
2205+ LValue CodeGenFunction::EmitArraySubscriptExpr (const ArraySubscriptExpr *E,
2206+ bool Accessed) {
21252207 // The index must always be an integer, which is not an aggregate. Emit it.
21262208 llvm::Value *Idx = EmitScalarExpr (E->getIdx ());
21272209 QualType IdxTy = E->getIdx ()->getType ();
21282210 bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType ();
21292211
2212+ if (SanOpts->Bounds )
2213+ EmitBoundsCheck (E, E->getBase (), Idx, IdxTy, Accessed);
2214+
21302215 // If the base is a vector type, then we are forming a vector element lvalue
21312216 // with this subscript.
21322217 if (E->getBase ()->getType ()->isVectorType ()) {
@@ -2187,7 +2272,13 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
21872272 // "gep x, i" here. Emit one "gep A, 0, i".
21882273 assert (Array->getType ()->isArrayType () &&
21892274 " 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);
21912282 llvm::Value *ArrayPtr = ArrayLV.getAddress ();
21922283 llvm::Value *Zero = llvm::ConstantInt::get (Int32Ty, 0 );
21932284 llvm::Value *Args[] = { Zero, Idx };
0 commit comments