22#include "llvm/ADT/SmallString.h"
23#include "llvm/ADT/iterator_range.h"
24#include "llvm/Support/raw_ostream.h"
31typedef std::pair<const TypeSourceInfo *, const CallExpr *> TypeCallPair;
32typedef llvm::PointerUnion<const Stmt *, const VarDecl *> ExprParent;
34class CastedAllocFinder
40 ExprParent CastedExprParent;
41 const Expr *CastedExpr;
45 CallRecord(ExprParent CastedExprParent,
const Expr *CastedExpr,
48 : CastedExprParent(CastedExprParent), CastedExpr(CastedExpr),
49 ExplicitCastType(ExplicitCastType), AllocCall(AllocCall) {}
52 typedef std::vector<CallRecord> CallVec;
56 II_malloc(&Ctx->Idents.get(
"malloc")),
57 II_calloc(&Ctx->Idents.get(
"calloc")),
58 II_realloc(&Ctx->Idents.get(
"realloc")) {}
60 void VisitChild(ExprParent
Parent,
const Stmt *S) {
61 TypeCallPair AllocCall =
Visit(S);
62 if (AllocCall.second && AllocCall.second != S)
63 Calls.push_back(CallRecord(
Parent, cast<Expr>(S), AllocCall.first,
67 void VisitChildren(
const Stmt *S) {
68 for (
const Stmt *Child : S->children())
73 TypeCallPair VisitCastExpr(
const CastExpr *
E) {
74 return Visit(
E->getSubExpr());
78 return TypeCallPair(
E->getTypeInfoAsWritten(),
79 Visit(
E->getSubExpr()).second);
82 TypeCallPair VisitParenExpr(
const ParenExpr *
E) {
83 return Visit(
E->getSubExpr());
86 TypeCallPair VisitStmt(
const Stmt *S) {
88 return TypeCallPair();
91 TypeCallPair VisitCallExpr(
const CallExpr *
E) {
96 if (II == II_malloc || II == II_calloc || II == II_realloc)
99 return TypeCallPair();
102 TypeCallPair VisitDeclStmt(
const DeclStmt *S) {
103 for (
const auto *I : S->decls())
104 if (
const VarDecl *VD = dyn_cast<VarDecl>(I))
105 if (
const Expr *
Init = VD->getInit())
106 VisitChild(VD,
Init);
107 return TypeCallPair();
113 std::vector<const UnaryExprOrTypeTraitExpr *> Sizeofs;
121 return Visit(
E->getSubExpr());
125 return Visit(
E->getSubExpr());
129 if (
E->getKind() != UETT_SizeOf)
132 Sizeofs.push_back(
E);
170 QualType ElemType = AT->getElementType();
171 if (typesCompatible(
C, PT, AT->getElementType()))
179class MallocSizeofChecker :
public Checker<check::ASTCodeBody> {
186 for (
const auto &CallRec : Finder.Calls) {
187 QualType CastedType = CallRec.CastedExpr->getType();
194 for (
const Expr *Arg : CallRec.AllocCall->arguments()) {
195 if (!Arg->getType()->isIntegralOrUnscopedEnumerationType())
198 SizeofFinder SFinder;
200 if (SFinder.Sizeofs.size() != 1)
203 QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();
205 if (typesCompatible(BR.
getContext(), PointeeType, SizeofType))
210 if (compatibleWithArrayType(BR.
getContext(), PointeeType, SizeofType))
214 if (CallRec.CastedExprParent.is<
const VarDecl *>()) {
215 TSI = CallRec.CastedExprParent.get<
const VarDecl *>()
216 ->getTypeSourceInfo();
218 TSI = CallRec.ExplicitCastType;
222 llvm::raw_svector_ostream
OS(buf);
226 if (Callee &&
Callee->getIdentifier())
227 OS <<
'\'' <<
Callee->getIdentifier()->getName() <<
'\'';
230 OS <<
" is converted to a pointer of type '" << PointeeType
231 <<
"', which is incompatible with "
232 <<
"sizeof operand type '" << SizeofType <<
"'";
234 Ranges.push_back(CallRec.AllocCall->getCallee()->getSourceRange());
235 Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
255bool 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 ...
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
A builtin binary operation expression such as "x + y" or "x <= y".
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ExplicitCastExpr - An explicit cast written in the source code.
This represents one expression.
Represents a function declaration or definition.
One of these records is kept for each identifier that is lexed.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
ParenExpr - This represents a parenthesized expression, e.g.
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
RetTy Visit(PTR(Stmt) S, ParamTys... P)
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
Get the full source range.
A container of type source information.
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 ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
const T * getAs() const
Member-template getAs<specific type>'.
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Represents a variable declaration or definition.
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
BugReporter is a utility class for generating PathDiagnostics for analysis.
const SourceManager & getSourceManager()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=std::nullopt, ArrayRef< FixItHint > Fixits=std::nullopt)
ASTContext & getContext()
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
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