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 {
162 Region = getPointedRegion(Region, C);
166 bool IsPolymorphic =
false;
169 getArrayRegion(Region, IsPolymorphic, Kind, C)) {
175 this,
"Dangerous pointer arithmetic",
176 "Pointer arithmetic on a pointer to base class is dangerous " 177 "because derived and base class may have different size."));
178 auto R = llvm::make_unique<BugReport>(*BT_polyArray,
179 BT_polyArray->getDescription(), N);
181 R->markInteresting(ArrayRegion);
187 if (Kind == AllocKind::Reinterpreted)
191 if (Kind != AllocKind::SingleObject &&
192 Region->
getKind() == MemRegion::Kind::SymbolicRegionKind)
196 if (!BT_pointerArith)
197 BT_pointerArith.reset(
new BuiltinBug(
this,
"Dangerous pointer arithmetic",
198 "Pointer arithmetic on non-array " 199 "variables relies on memory layout, " 200 "which is dangerous."));
201 auto R = llvm::make_unique<BugReport>(*BT_pointerArith,
202 BT_pointerArith->getDescription(), N);
204 R->markInteresting(Region);
209 void PointerArithChecker::initAllocIdentifiers(
ASTContext &C)
const {
210 if (!AllocFunctions.empty())
212 AllocFunctions.insert(&C.
Idents.
get(
"alloca"));
213 AllocFunctions.insert(&C.
Idents.
get(
"malloc"));
214 AllocFunctions.insert(&C.
Idents.
get(
"realloc"));
215 AllocFunctions.insert(&C.
Idents.
get(
"calloc"));
216 AllocFunctions.insert(&C.
Idents.
get(
"valloc"));
219 void PointerArithChecker::checkPostStmt(
const CallExpr *CE,
227 if (AllocFunctions.count(FunI) == 0)
238 State = State->set<RegionState>(Region, AllocKind::Array);
242 void PointerArithChecker::checkPostStmt(
const CXXNewExpr *NE,
255 State = State->set<RegionState>(Region,
Kind);
259 void PointerArithChecker::checkPostStmt(
const CastExpr *CE,
273 State = State->set<RegionState>(Region, AllocKind::Reinterpreted);
277 void PointerArithChecker::checkPreStmt(
const CastExpr *CE,
279 if (CE->
getCastKind() != CastKind::CK_ArrayToPointerDecay)
290 if (
const AllocKind *
Kind = State->get<RegionState>(Region)) {
291 if (*
Kind == AllocKind::Array || *
Kind == AllocKind::Reinterpreted)
294 State = State->set<RegionState>(Region, AllocKind::Array);
298 void PointerArithChecker::checkPreStmt(
const UnaryOperator *UOp,
302 reportPointerArithMisuse(UOp->
getSubExpr(), C,
true);
313 reportPointerArithMisuse(SubsExpr->
getBase(), C);
319 if (!BOp->
isAdditiveOp() && OpKind != BO_AddAssign && OpKind != BO_SubAssign)
328 if (State->isNull(RHSVal).isConstrainedTrue())
335 if (State->isNull(LHSVal).isConstrainedTrue())
337 reportPointerArithMisuse(Rhs, C);
An instance of this class is created to represent 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).
Defines the clang::Expr interface and subclasses for C++ expressions.
IdentifierInfo * getIdentifier() const
getIdentifier - 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.
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.
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.
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.
const LocationContext * getLocationContext() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.