Index: lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp +++ lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp @@ -24,17 +24,20 @@ namespace { class ArrayBoundChecker : - public Checker { + public Checker> { mutable std::unique_ptr BT; + mutable std::unique_ptr BT_VLA; public: void checkLocation(SVal l, bool isLoad, const Stmt* S, CheckerContext &C) const; + void checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const; }; } void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS, CheckerContext &C) const { + // Check for out of bound array element access. const MemRegion *R = l.getAsRegion(); if (!R) @@ -88,6 +91,39 @@ C.addTransition(StInBound); } +void ArrayBoundChecker::checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const +{ + const Expr *Base = A->getBase()->IgnoreImpCasts(); + + ASTContext &Ctx = C.getASTContext(); + const VariableArrayType *VLA = Ctx.getAsVariableArrayType(Base->getType()); + if (!VLA) + return; + + ProgramStateRef State = C.getState(); + SVal sizeV = State->getSVal(VLA->getSizeExpr(), C.getLocationContext()); + SVal idxV = State->getSVal(A->getIdx(), C.getLocationContext()); + + // Is idx greater than size? + SValBuilder &Bldr = C.getSValBuilder(); + SVal GE = Bldr.evalBinOp(State, BO_GE, idxV, sizeV, Bldr.getConditionType()); + if (!GE.isConstant(1)) + return; + + ExplodedNode *N = C.generateErrorNode(State); + if (!N) + return; + + if (!BT_VLA) + BT_VLA.reset(new BuiltinBug( + this, "Out-of-bound VLA access", + "Out-of-bounds VLA access (symbolically this index is greater than the size)")); + // Generate a report for this bug. + auto report = llvm::make_unique(*BT_VLA, BT_VLA->getDescription(), N); + report->addRange(A->getSourceRange()); + C.emitReport(std::move(report)); +} + void ento::registerArrayBoundChecker(CheckerManager &mgr) { mgr.registerChecker(); }