23 using namespace clang;
38 ID.AddInteger(static_cast<int>(X));
44 class PointerArithChecker
46 check::PreStmt<BinaryOperator>, check::PreStmt<UnaryOperator>,
47 check::PreStmt<ArraySubscriptExpr>, check::PreStmt<CastExpr>,
48 check::PostStmt<CastExpr>, check::PostStmt<CXXNewExpr>,
49 check::PostStmt<CallExpr>, check::DeadSymbols> {
56 bool PointedNeeded =
false)
const;
57 void initAllocIdentifiers(
ASTContext &C)
const;
59 mutable std::unique_ptr<BuiltinBug> BT_pointerArith;
60 mutable std::unique_ptr<BuiltinBug> BT_polyArray;
61 mutable llvm::SmallSet<IdentifierInfo *, 8> AllocFunctions;
77 void PointerArithChecker::checkDeadSymbols(
SymbolReaper &SR,
95 if (isa<CXXMethodDecl>(FD))
100 return AllocKind::Array;
102 return AllocKind::SingleObject;
106 PointerArithChecker::getPointedRegion(
const MemRegion *Region,
110 SVal S = State->getSVal(Region);
123 while (Region->
getKind() == MemRegion::Kind::CXXBaseObjectRegionKind) {
127 if (Region->
getKind() == MemRegion::Kind::ElementRegionKind) {
132 if (
const AllocKind *
Kind = State->get<RegionState>(Region)) {
134 if (*
Kind == AllocKind::Array)
141 if (Region->
getKind() == MemRegion::Kind::SymbolicRegionKind)
149 void PointerArithChecker::reportPointerArithMisuse(
const Expr *E,
151 bool PointedNeeded)
const {
161 Region = getPointedRegion(Region, C);
165 bool IsPolymorphic =
false;
168 getArrayRegion(Region, IsPolymorphic, Kind, C)) {
174 this,
"Dangerous pointer arithmetic",
175 "Pointer arithmetic on a pointer to base class is dangerous " 176 "because derived and base class may have different size."));
177 auto R = llvm::make_unique<BugReport>(*BT_polyArray,
178 BT_polyArray->getDescription(), N);
180 R->markInteresting(ArrayRegion);
186 if (Kind == AllocKind::Reinterpreted)
190 if (Kind != AllocKind::SingleObject &&
191 Region->
getKind() == MemRegion::Kind::SymbolicRegionKind)
195 if (!BT_pointerArith)
196 BT_pointerArith.reset(
new BuiltinBug(
this,
"Dangerous pointer arithmetic",
197 "Pointer arithmetic on non-array " 198 "variables relies on memory layout, " 199 "which is dangerous."));
200 auto R = llvm::make_unique<BugReport>(*BT_pointerArith,
201 BT_pointerArith->getDescription(), N);
203 R->markInteresting(Region);
208 void PointerArithChecker::initAllocIdentifiers(
ASTContext &C)
const {
209 if (!AllocFunctions.empty())
211 AllocFunctions.insert(&C.
Idents.
get(
"alloca"));
212 AllocFunctions.insert(&C.
Idents.
get(
"malloc"));
213 AllocFunctions.insert(&C.
Idents.
get(
"realloc"));
214 AllocFunctions.insert(&C.
Idents.
get(
"calloc"));
215 AllocFunctions.insert(&C.
Idents.
get(
"valloc"));
218 void PointerArithChecker::checkPostStmt(
const CallExpr *CE,
226 if (AllocFunctions.count(FunI) == 0)
237 State = State->set<RegionState>(Region, AllocKind::Array);
241 void PointerArithChecker::checkPostStmt(
const CXXNewExpr *NE,
254 State = State->set<RegionState>(Region,
Kind);
258 void PointerArithChecker::checkPostStmt(
const CastExpr *CE,
272 State = State->set<RegionState>(Region, AllocKind::Reinterpreted);
276 void PointerArithChecker::checkPreStmt(
const CastExpr *CE,
278 if (CE->
getCastKind() != CastKind::CK_ArrayToPointerDecay)
289 if (
const AllocKind *
Kind = State->get<RegionState>(Region)) {
290 if (*
Kind == AllocKind::Array || *
Kind == AllocKind::Reinterpreted)
293 State = State->set<RegionState>(Region, AllocKind::Array);
297 void PointerArithChecker::checkPreStmt(
const UnaryOperator *UOp,
301 reportPointerArithMisuse(UOp->
getSubExpr(), C,
true);
315 reportPointerArithMisuse(SubsExpr->
getBase(), C);
321 if (!BOp->
isAdditiveOp() && OpKind != BO_AddAssign && OpKind != BO_SubAssign)
330 if (State->isNull(RHSVal).isConstrainedTrue())
337 if (State->isNull(LHSVal).isConstrainedTrue())
339 reportPointerArithMisuse(Rhs, C);
Represents a function declaration or definition.
MemRegion - The root abstract class for all memory regions.
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
FunctionDecl * getOperatorNew() const
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
Defines the clang::Expr interface and subclasses for C++ expressions.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
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 ...
static void Profile(AllocKind X, FoldingSetNodeID &ID)
static bool isIncrementDecrementOp(Opcode Op)
A builtin binary operation expression such as "x + y" or "x <= y".
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.
const RegionTy * getAs() const
Expr - This represents one expression.
bool isVariadic() const
Whether this function is variadic.
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.
CHECKER * registerChecker(AT... Args)
Used to register checkers.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Expr * getSubExpr() const
CastKind getCastKind() const
const MemRegion * getAsRegion() const
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.
bool isVectorType() const
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
bool isZeroConstant() const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const ProgramStateRef & getState() const
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).
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ElementRegin is used to represent both array elements and casts.
bool isPointerType() const
A trivial tuple used to represent a source range.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.