diff options
author | Kaelyn Uhrain <rikka@google.com> | 2011-08-05 23:18:04 +0000 |
---|---|---|
committer | Kaelyn Uhrain <rikka@google.com> | 2011-08-05 23:18:04 +0000 |
commit | d6c8865e6f306556b7eef972ceec2cc8ba026a0d (patch) | |
tree | b0391b68d4b12d90d9fbda7d2a144eb2ab29bf45 /lib/Sema/SemaExpr.cpp | |
parent | de91db51c1488b14a7a23b24d8a81dce1ec63f4f (diff) |
Perform array bounds checking in more situations and properly handle special
case situations with the unary operators & and *. Also extend the array bounds
checking to work with pointer arithmetic; the pointer arithemtic checking can
be turned on using -Warray-bounds-pointer-arithmetic.
The changes to where CheckArrayAccess gets called is based on some trial &
error and a bunch of digging through source code and gdb backtraces in order
to have the check performed under as many situations as possible (such as for
variable initializers, arguments to function calls, and within conditional in
addition to the simpler cases of the operands to binary and unary operator)
while not being called--and triggering warnings--more than once for a given
ArraySubscriptExpr.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136997 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bc7d0bdfe5..5e092b7c06 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -322,6 +322,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // A glvalue of a non-function, non-array type T can be // converted to a prvalue. if (!E->isGLValue()) return Owned(E); + QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); @@ -364,8 +365,6 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // type of the lvalue. if (T.hasQualifiers()) T = T.getUnqualifiedType(); - - CheckArrayAccess(E); return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, 0, VK_RValue)); @@ -3397,6 +3396,12 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, Arg = ArgExpr.takeAs<Expr>(); } + + // Check for array bounds violations for each argument to the call. This + // check only triggers warnings when the argument isn't a more complex Expr + // with its own checking, such as a BinaryOperator. + CheckArrayAccess(Arg); + AllArgs.push_back(Arg); } @@ -5935,6 +5940,9 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 return QualType(); } + // Check array bounds for pointer arithemtic + CheckArrayAccess(PExp, IExp); + if (CompLHSTy) { QualType LHSTy = Context.isPromotableBitField(lex.get()); if (LHSTy.isNull()) { @@ -5991,6 +5999,12 @@ QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex, if (!checkArithmeticOpPointerOperand(*this, Loc, lex.get())) return QualType(); + Expr *IExpr = rex.get()->IgnoreParenCasts(); + UnaryOperator negRex(IExpr, UO_Minus, IExpr->getType(), VK_RValue, + OK_Ordinary, IExpr->getExprLoc()); + // Check array bounds for pointer arithemtic + CheckArrayAccess(lex.get()->IgnoreParenCasts(), &negRex); + if (CompLHSTy) *CompLHSTy = lex.get()->getType(); return lex.get()->getType(); } @@ -6984,9 +6998,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, ExprResult &RHS, return QualType(); CheckForNullPointerDereference(*this, LHS); - // Check for trivial buffer overflows. - CheckArrayAccess(LHS->IgnoreParenCasts()); - + // C99 6.5.16p3: The type of an assignment expression is the type of the // left operand unless the left operand has qualified type, in which case // it is the unqualified version of the type of the left operand. @@ -7721,6 +7733,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, } if (ResultTy.isNull() || lhs.isInvalid() || rhs.isInvalid()) return ExprError(); + + // Check for array bounds violations for both sides of the BinaryOperator + CheckArrayAccess(lhs.get()); + CheckArrayAccess(rhs.get()); + if (CompResultTy.isNull()) return Owned(new (Context) BinaryOperator(lhs.take(), rhs.take(), Opc, ResultTy, VK, OK, OpLoc)); @@ -8071,6 +8088,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, if (resultType.isNull() || Input.isInvalid()) return ExprError(); + // Check for array bounds violations in the operand of the UnaryOperator, + // except for the '*' and '&' operators that have to be handled specially + // by CheckArrayAccess (as there are special cases like &array[arraysize] + // that are explicitly defined as valid by the standard). + if (Opc != UO_AddrOf && Opc != UO_Deref) + CheckArrayAccess(Input.get()); + return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType, VK, OK, OpLoc)); } |