22#include "llvm/Support/raw_ostream.h"
29typedef std::pair<const TypeSourceInfo *, const CallExpr *> TypeCallPair;
30typedef llvm::PointerUnion<const Stmt *, const VarDecl *> ExprParent;
32class CastedAllocFinder
34 IdentifierInfo *II_malloc, *II_calloc, *II_realloc;
38 ExprParent CastedExprParent;
39 const Expr *CastedExpr;
40 const TypeSourceInfo *ExplicitCastType;
41 const CallExpr *AllocCall;
43 CallRecord(ExprParent CastedExprParent,
const Expr *CastedExpr,
44 const TypeSourceInfo *ExplicitCastType,
45 const CallExpr *AllocCall)
46 : CastedExprParent(CastedExprParent), CastedExpr(CastedExpr),
47 ExplicitCastType(ExplicitCastType), AllocCall(AllocCall) {}
50 typedef std::vector<CallRecord> CallVec;
53 CastedAllocFinder(ASTContext *Ctx) :
54 II_malloc(&Ctx->Idents.get(
"malloc")),
55 II_calloc(&Ctx->Idents.get(
"calloc")),
56 II_realloc(&Ctx->Idents.get(
"realloc")) {}
58 void VisitChild(ExprParent Parent,
const Stmt *S) {
59 TypeCallPair AllocCall = Visit(S);
60 if (AllocCall.second && AllocCall.second != S)
61 Calls.push_back(CallRecord(Parent,
cast<Expr>(S), AllocCall.first,
65 void VisitChildren(
const Stmt *S) {
66 for (
const Stmt *Child : S->
children())
71 TypeCallPair VisitCastExpr(
const CastExpr *E) {
75 TypeCallPair VisitExplicitCastExpr(
const ExplicitCastExpr *E) {
80 TypeCallPair VisitParenExpr(
const ParenExpr *E) {
84 TypeCallPair VisitStmt(
const Stmt *S) {
86 return TypeCallPair();
89 TypeCallPair VisitCallExpr(
const CallExpr *E) {
94 if (II == II_malloc || II == II_calloc || II == II_realloc)
95 return TypeCallPair((
const TypeSourceInfo *)
nullptr, E);
97 return TypeCallPair();
100 TypeCallPair VisitDeclStmt(
const DeclStmt *S) {
101 for (
const auto *I : S->
decls())
102 if (
const VarDecl *VD = dyn_cast<VarDecl>(I))
103 if (
const Expr *
Init = VD->getInit())
104 VisitChild(VD,
Init);
105 return TypeCallPair();
111 std::vector<const UnaryExprOrTypeTraitExpr *> Sizeofs;
113 void VisitBinMul(
const BinaryOperator *E) {
118 void VisitImplicitCastExpr(
const ImplicitCastExpr *E) {
122 void VisitParenExpr(
const ParenExpr *E) {
126 void VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *E) {
127 if (E->
getKind() != UETT_SizeOf)
130 Sizeofs.push_back(E);
167 while (
const ArrayType *AT =
T->getAsArrayTypeUnsafe()) {
168 QualType ElemType = AT->getElementType();
169 if (typesCompatible(
C, PT, AT->getElementType()))
177class MallocSizeofChecker :
public Checker<check::ASTCodeBody> {
179 void checkASTCodeBody(
const Decl *D, AnalysisManager& mgr,
180 BugReporter &BR)
const {
184 for (
const auto &CallRec : Finder.Calls) {
185 QualType CastedType = CallRec.CastedExpr->getType();
192 for (
const Expr *Arg : CallRec.AllocCall->arguments()) {
193 if (!Arg->getType()->isIntegralOrUnscopedEnumerationType())
196 SizeofFinder SFinder;
198 if (SFinder.Sizeofs.size() != 1)
201 QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();
203 if (typesCompatible(BR.
getContext(), PointeeType, SizeofType))
208 if (compatibleWithArrayType(BR.
getContext(), PointeeType, SizeofType))
211 const TypeSourceInfo *TSI =
nullptr;
213 dyn_cast<const VarDecl *>(CallRec.CastedExprParent)) {
214 TSI = VD->getTypeSourceInfo();
216 TSI = CallRec.ExplicitCastType;
220 llvm::raw_svector_ostream
OS(buf);
223 const FunctionDecl *
Callee = CallRec.AllocCall->getDirectCallee();
224 if (Callee &&
Callee->getIdentifier())
225 OS <<
'\'' <<
Callee->getIdentifier()->getName() <<
'\'';
228 OS <<
" is converted to a pointer of type '" << PointeeType
229 <<
"', which is incompatible with "
230 <<
"sizeof operand type '" << SizeofType <<
"'";
231 SmallVector<SourceRange, 4> Ranges;
232 Ranges.push_back(CallRec.AllocCall->getCallee()->getSourceRange());
233 Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
253bool ento::shouldRegisterMallocSizeofChecker(
const CheckerManager &mgr) {
Defines the clang::TypeLoc interface and its subclasses.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
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...
TypeSourceInfo * getTypeInfoAsWritten() const
getTypeInfoAsWritten - Returns the type source info for the type that this expression is casting to.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
QualType getCanonicalType() const
SourceRange getSourceRange() const LLVM_READONLY
Get the full source range.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
bool isVoidPointerType() const
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const T * getAs() const
Member-template getAs<specific type>'.
UnaryExprOrTypeTrait getKind() const
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
const SourceManager & getSourceManager()
ASTContext & getContext()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerFrontend *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
const char *const UnixAPI
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
U cast(CodeGen::Address addr)