26 #include "llvm/ADT/SmallVector.h"
28 using namespace clang;
32 struct MallocOverflowCheck {
37 : mulop(m), variable (v)
41 class MallocOverflowSecurityChecker :
public Checker<check::ASTCodeBody> {
46 void CheckMallocArgument(
50 void OutputPossibleOverflows(
57 void MallocOverflowSecurityChecker::CheckMallocArgument(
59 const Expr *TheArgument,
67 const Expr * e = TheArgument;
72 if (isa<BinaryOperator>(e)) {
76 if (mulop ==
nullptr && opc ==
BO_Mul)
91 else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e))
106 PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e));
111 class CheckOverflowOps :
117 theVecType &toScanFor;
120 bool isIntZeroExpr(
const Expr *E)
const {
129 void CheckExpr(
const Expr *E_p) {
132 theVecType::iterator i = toScanFor.end();
133 theVecType::iterator e = toScanFor.begin();
135 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
136 const Decl * EdreD = DR->getDecl();
139 if (
const DeclRefExpr *DR_i = dyn_cast<DeclRefExpr>(i->variable)) {
140 if (DR_i->getDecl() == EdreD)
141 i = toScanFor.erase(i);
145 else if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
147 const Decl *EmeMD = ME->getMemberDecl();
150 if (
const auto *ME_i = dyn_cast<MemberExpr>(i->variable)) {
151 if (ME_i->getMemberDecl() == EmeMD)
152 i = toScanFor.erase (i);
165 if (!isIntZeroExpr(lhs) && ! isIntZeroExpr(rhs)) {
176 return this->Visit(S->
getBody());
178 void VisitForStmt(
ForStmt *S) {
179 return this->Visit(S->
getBody());
181 void VisitDoStmt(
DoStmt *S) {
182 return this->Visit(S->
getBody());
187 toScanFor(v), Context(ctx)
199 void MallocOverflowSecurityChecker::OutputPossibleOverflows(
203 if (PossibleMallocOverflows.empty())
207 CheckOverflowOps c(PossibleMallocOverflows, BR.
getContext());
211 for (CheckOverflowOps::theVecType::iterator
212 i = PossibleMallocOverflows.begin(),
213 e = PossibleMallocOverflows.end();
218 "the computation of the size of the memory allocation may overflow",
221 i->mulop->getSourceRange());
225 void MallocOverflowSecurityChecker::checkASTCodeBody(
const Decl *D,
241 if (
const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) {
253 if (FnInfo->
isStr (
"malloc") || FnInfo->
isStr (
"_MALLOC")) {
254 if (TheCall->getNumArgs() == 1)
255 CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0),
263 OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr);
267 ento::registerMallocOverflowSecurityChecker(
CheckerManager &mgr) {
EvaluatedExprVisitor - This class visits 'Expr *'s.
bool isEvaluatable(const ASTContext &Ctx) const
IdentifierInfo * getIdentifier() const
const char *const UnixAPI
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
ASTContext & getContext()
A builtin binary operation expression such as "x + y" or "x <= y".
ASTContext & getASTContext() override
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
Stmt * getBody() const
Get the body of the Declaration.
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
CFG * getCFG(Decl const *D)
The result type of a method or function.
ElementList::iterator iterator
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
CHECKER * registerChecker()
Used to register checkers.
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
Expr * IgnoreParenImpCasts() LLVM_READONLY
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
SourceManager & getSourceManager()
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].
static bool isComparisonOp(Opcode Opc)