22 #include "llvm/ADT/SmallVector.h"
24 using namespace clang;
39 ID.AddInteger(static_cast<int>(X));
45 class PointerArithChecker
47 check::PreStmt<BinaryOperator>, check::PreStmt<UnaryOperator>,
48 check::PreStmt<ArraySubscriptExpr>, check::PreStmt<CastExpr>,
49 check::PostStmt<CastExpr>, check::PostStmt<CXXNewExpr>,
50 check::PostStmt<CallExpr>, check::DeadSymbols> {
57 bool PointedNeeded =
false)
const;
58 void initAllocIdentifiers(
ASTContext &C)
const;
60 mutable std::unique_ptr<BuiltinBug> BT_pointerArith;
61 mutable std::unique_ptr<BuiltinBug> BT_polyArray;
62 mutable llvm::SmallSet<IdentifierInfo *, 8> AllocFunctions;
78 void PointerArithChecker::checkDeadSymbols(
SymbolReaper &SR,
96 if (isa<CXXMethodDecl>(FD))
101 return AllocKind::Array;
103 return AllocKind::SingleObject;
107 PointerArithChecker::getPointedRegion(
const MemRegion *Region,
111 SVal S = State->getSVal(Region);
124 while (Region->
getKind() == MemRegion::Kind::CXXBaseObjectRegionKind) {
128 if (Region->
getKind() == MemRegion::Kind::ElementRegionKind) {
133 if (
const AllocKind *
Kind = State->get<RegionState>(Region)) {
135 if (*
Kind == AllocKind::Array)
142 if (Region->
getKind() == MemRegion::Kind::SymbolicRegionKind)
150 void PointerArithChecker::reportPointerArithMisuse(
const Expr *
E,
152 bool PointedNeeded)
const {
163 Region = getPointedRegion(Region, C);
167 bool IsPolymorphic =
false;
170 getArrayRegion(Region, IsPolymorphic, Kind, C)) {
176 this,
"Dangerous pointer arithmetic",
177 "Pointer arithmetic on a pointer to base class is dangerous "
178 "because derived and base class may have different size."));
179 auto R = llvm::make_unique<BugReport>(*BT_polyArray,
180 BT_polyArray->getDescription(), N);
181 R->addRange(E->getSourceRange());
182 R->markInteresting(ArrayRegion);
188 if (Kind == AllocKind::Reinterpreted)
192 if (Kind != AllocKind::SingleObject &&
193 Region->
getKind() == MemRegion::Kind::SymbolicRegionKind)
197 if (!BT_pointerArith)
198 BT_pointerArith.reset(
new BuiltinBug(
this,
"Dangerous pointer arithmetic",
199 "Pointer arithmetic on non-array "
200 "variables relies on memory layout, "
201 "which is dangerous."));
202 auto R = llvm::make_unique<BugReport>(*BT_pointerArith,
203 BT_pointerArith->getDescription(), N);
205 R->markInteresting(Region);
210 void PointerArithChecker::initAllocIdentifiers(
ASTContext &C)
const {
211 if (!AllocFunctions.empty())
213 AllocFunctions.insert(&C.
Idents.
get(
"alloca"));
214 AllocFunctions.insert(&C.
Idents.
get(
"malloc"));
215 AllocFunctions.insert(&C.
Idents.
get(
"realloc"));
216 AllocFunctions.insert(&C.
Idents.
get(
"calloc"));
217 AllocFunctions.insert(&C.
Idents.
get(
"valloc"));
220 void PointerArithChecker::checkPostStmt(
const CallExpr *CE,
228 if (AllocFunctions.count(FunI) == 0)
239 State = State->set<RegionState>(Region, AllocKind::Array);
243 void PointerArithChecker::checkPostStmt(
const CXXNewExpr *NE,
256 State = State->set<RegionState>(Region,
Kind);
260 void PointerArithChecker::checkPostStmt(
const CastExpr *CE,
274 State = State->set<RegionState>(Region, AllocKind::Reinterpreted);
278 void PointerArithChecker::checkPreStmt(
const CastExpr *CE,
280 if (CE->
getCastKind() != CastKind::CK_ArrayToPointerDecay)
291 if (
const AllocKind *Kind = State->get<RegionState>(Region)) {
292 if (*Kind == AllocKind::Array || *Kind == AllocKind::Reinterpreted)
295 State = State->set<RegionState>(Region, AllocKind::Array);
299 void PointerArithChecker::checkPreStmt(
const UnaryOperator *UOp,
303 reportPointerArithMisuse(UOp->
getSubExpr(), C,
true);
314 reportPointerArithMisuse(SubsExpr->
getBase(), C);
320 if (!BOp->
isAdditiveOp() && OpKind != BO_AddAssign && OpKind != BO_SubAssign)
329 if (State->isNull(RHSVal).isConstrainedTrue())
336 if (State->isNull(LHSVal).isConstrainedTrue())
338 reportPointerArithMisuse(Rhs, C);
CastKind getCastKind() const
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
MemRegion - The root abstract class for all memory regions.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
const RegionTy * getAs() const
bool isZeroConstant() const
Defines the clang::Expr interface and subclasses for C++ expressions.
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
static void Profile(AllocKind X, FoldingSetNodeID &ID)
static bool isIncrementDecrementOp(Opcode Op)
A builtin binary operation expression such as "x + y" or "x <= y".
bool isVariadic() const
Whether this function is variadic.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Expr - This represents one expression.
const ProgramStateRef & getState() const
Expr * getSubExpr() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
unsigned getNumParams() const
getNumParams - Return the number of parameters this function must have based on its FunctionType...
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
A class responsible for cleaning up unused symbols.
ASTContext & getASTContext()
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
FunctionDecl * getOperatorNew() const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
static bool isAdditiveOp(Opcode Opc)
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ElementRegin is used to represent both array elements and casts.
A trivial tuple used to represent a source range.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const LocationContext * getLocationContext() const
bool isPointerType() const