22 #include "llvm/ADT/SmallString.h" 23 #include "llvm/Support/raw_ostream.h" 25 using namespace clang;
30 typedef std::pair<const TypeSourceInfo *, const CallExpr *> TypeCallPair;
31 typedef llvm::PointerUnion<const Stmt *, const VarDecl *> ExprParent;
33 class CastedAllocFinder
39 ExprParent CastedExprParent;
40 const Expr *CastedExpr;
44 CallRecord(ExprParent CastedExprParent,
const Expr *CastedExpr,
47 : CastedExprParent(CastedExprParent), CastedExpr(CastedExpr),
48 ExplicitCastType(ExplicitCastType), AllocCall(AllocCall) {}
51 typedef std::vector<CallRecord> CallVec;
55 II_malloc(&Ctx->Idents.get(
"malloc")),
56 II_calloc(&Ctx->Idents.get(
"calloc")),
57 II_realloc(&Ctx->Idents.get(
"realloc")) {}
59 void VisitChild(ExprParent
Parent,
const Stmt *S) {
60 TypeCallPair AllocCall = Visit(S);
61 if (AllocCall.second && AllocCall.second != S)
62 Calls.push_back(CallRecord(Parent, cast<Expr>(S), AllocCall.first,
66 void VisitChildren(
const Stmt *S) {
72 TypeCallPair VisitCastExpr(
const CastExpr *E) {
81 TypeCallPair VisitParenExpr(
const ParenExpr *E) {
85 TypeCallPair VisitStmt(
const Stmt *S) {
87 return TypeCallPair();
90 TypeCallPair VisitCallExpr(
const CallExpr *E) {
95 if (II == II_malloc || II == II_calloc || II == II_realloc)
98 return TypeCallPair();
101 TypeCallPair VisitDeclStmt(
const DeclStmt *S) {
102 for (
const auto *I : S->
decls())
103 if (
const VarDecl *VD = dyn_cast<VarDecl>(I))
104 if (
const Expr *Init = VD->getInit())
105 VisitChild(VD, Init);
106 return TypeCallPair();
112 std::vector<const UnaryExprOrTypeTraitExpr *> Sizeofs;
123 void VisitParenExpr(
const ParenExpr *E) {
131 Sizeofs.push_back(E);
165 QualType ElemType = AT->getElementType();
166 if (typesCompatible(C, PT, AT->getElementType()))
174 class MallocSizeofChecker :
public Checker<check::ASTCodeBody> {
176 void checkASTCodeBody(
const Decl *D, AnalysisManager& mgr,
177 BugReporter &BR)
const {
179 CastedAllocFinder Finder(&BR.getContext());
181 for (CastedAllocFinder::CallVec::iterator i = Finder.Calls.begin(),
182 e = Finder.Calls.end(); i != e; ++i) {
183 QualType CastedType = i->CastedExpr->getType();
191 ae = i->AllocCall->arg_end(); ai != ae; ++ai) {
192 if (!(*ai)->getType()->isIntegralOrUnscopedEnumerationType())
195 SizeofFinder SFinder;
197 if (SFinder.Sizeofs.size() != 1)
200 QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();
202 if (typesCompatible(BR.getContext(), PointeeType, SizeofType))
207 if (compatibleWithArrayType(BR.getContext(), PointeeType, SizeofType))
211 if (i->CastedExprParent.is<
const VarDecl *>()) {
213 i->CastedExprParent.get<
const VarDecl *>()->getTypeSourceInfo();
215 TSI = i->ExplicitCastType;
219 llvm::raw_svector_ostream
OS(buf);
222 const FunctionDecl *Callee = i->AllocCall->getDirectCallee();
227 OS <<
" is converted to a pointer of type '" 228 << PointeeType.
getAsString() <<
"', which is incompatible with " 229 <<
"sizeof operand type '" << SizeofType.
getAsString() <<
"'";
231 Ranges.push_back(i->AllocCall->getCallee()->getSourceRange());
232 Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
236 PathDiagnosticLocation L =
238 BR.getSourceManager(), ADC);
240 BR.EmitBasicReport(D,
this,
"Allocator sizeof operand mismatch",
249 void ento::registerMallocSizeofChecker(CheckerManager &mgr) {
250 mgr.registerChecker<MallocSizeofChecker>();
253 bool ento::shouldRegisterMallocSizeofChecker(
const LangOptions &LO) {
Represents a function declaration or definition.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Stmt - This represents one statement.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Decl - This represents one declaration (or definition), e.g.
ParenExpr - This represents a parethesized expression, e.g.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
TypeSourceInfo * getTypeInfoAsWritten() const
getTypeInfoAsWritten - Returns the type source info for the type that this expression is casting to...
A container of type source information.
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
const char *const UnixAPI
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 ...
AnalysisDeclContext contains the context data for the function or method under analysis.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type...
A builtin binary operation expression such as "x + y" or "x <= y".
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
This represents one expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Defines the clang::TypeLoc interface and its subclasses.
const Expr * getSubExpr() const
bool isVoidPointerType() const
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
QualType getCanonicalType() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
UnaryExprOrTypeTrait getKind() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
StringRef getName() const
Return the actual identifier string.
Dataflow Directional Tag Classes.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
ExplicitCastExpr - An explicit cast written in the source code.
SourceRange getSourceRange() const LLVM_READONLY
Get the full source range.
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
Iterator for iterating over Stmt * arrays that contain only T *.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
bool isPointerType() const