26 #include "llvm/ADT/APSInt.h" 27 #include "llvm/ADT/SmallVector.h" 30 using namespace clang;
35 struct MallocOverflowCheck {
41 : mulop(m), variable(v), maxVal(
std::move(val)) {}
44 class MallocOverflowSecurityChecker :
public Checker<check::ASTCodeBody> {
46 void checkASTCodeBody(
const Decl *D, AnalysisManager &mgr,
47 BugReporter &BR)
const;
49 void CheckMallocArgument(
53 void OutputPossibleOverflows(
55 const Decl *D, BugReporter &BR, AnalysisManager &mgr)
const;
62 return (op == BO_Mul) && (Val == 0);
65 void MallocOverflowSecurityChecker::CheckMallocArgument(
67 const Expr *TheArgument,
75 const Expr *e = TheArgument;
85 if (mulop ==
nullptr && opc == BO_Mul)
87 if (opc != BO_Mul && opc != BO_Add && opc != BO_Sub && opc != BO_Shl)
90 const Expr *lhs = binop->getLHS();
91 const Expr *rhs = binop->getRHS();
97 }
else if ((opc == BO_Add || opc == BO_Mul) &&
106 else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e))
112 if (mulop ==
nullptr)
121 PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e, maxVal));
126 class CheckOverflowOps :
132 theVecType &toScanFor;
135 bool isIntZeroExpr(
const Expr *E)
const {
149 template <
typename T1>
150 void Erase(
const T1 *DR,
151 llvm::function_ref<
bool(
const MallocOverflowCheck &)> Pred) {
152 auto P = [DR, Pred](
const MallocOverflowCheck &Check) {
153 if (
const auto *CheckDR = dyn_cast<T1>(Check.variable))
154 return getDecl(CheckDR) == getDecl(DR) && Pred(Check);
157 toScanFor.erase(std::remove_if(toScanFor.begin(), toScanFor.end(),
P),
161 void CheckExpr(
const Expr *E_p) {
162 auto PredTrue = [](
const MallocOverflowCheck &) {
return true; };
164 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
165 Erase<DeclRefExpr>(DR, PredTrue);
166 else if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
167 Erase<MemberExpr>(ME, PredTrue);
177 bool assignKnown =
false;
178 bool numeratorKnown =
false, denomKnown =
false;
192 if (BOp->getOpcode() == BO_Div) {
201 numeratorKnown =
true;
204 if (!assignKnown && !denomKnown)
206 auto denomExtVal = denomVal.getExtValue();
215 auto pred = [assignKnown, numeratorKnown,
216 denomExtVal](
const MallocOverflowCheck &Check) {
217 return assignKnown ||
218 (numeratorKnown && (denomExtVal >= Check.maxVal.getExtValue()));
221 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
222 Erase<DeclRefExpr>(DR, pred);
223 else if (
const auto *ME = dyn_cast<MemberExpr>(E))
224 Erase<MemberExpr>(ME, pred);
234 if (!isIntZeroExpr(lhs) && !isIntZeroExpr(rhs)) {
240 CheckAssignmentExpr(E);
247 return this->Visit(S->
getBody());
249 void VisitForStmt(
ForStmt *S) {
250 return this->Visit(S->
getBody());
252 void VisitDoStmt(
DoStmt *S) {
253 return this->Visit(S->
getBody());
258 toScanFor(v), Context(ctx)
270 void MallocOverflowSecurityChecker::OutputPossibleOverflows(
272 const Decl *D, BugReporter &BR, AnalysisManager &mgr)
const {
274 if (PossibleMallocOverflows.empty())
278 CheckOverflowOps c(PossibleMallocOverflows, BR.getContext());
279 c.Visit(mgr.getAnalysisDeclContext(D)->getBody());
282 for (CheckOverflowOps::theVecType::iterator
283 i = PossibleMallocOverflows.begin(),
284 e = PossibleMallocOverflows.end();
289 "the computation of the size of the memory allocation may overflow",
291 BR.getSourceManager()),
292 i->mulop->getSourceRange());
296 void MallocOverflowSecurityChecker::checkASTCodeBody(
const Decl *D,
297 AnalysisManager &mgr,
298 BugReporter &BR)
const {
300 CFG *cfg = mgr.getCFG(D);
312 if (
const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) {
324 if (FnInfo->
isStr (
"malloc") || FnInfo->
isStr (
"_MALLOC")) {
325 if (TheCall->getNumArgs() == 1)
326 CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0),
327 mgr.getASTContext());
334 OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr);
338 ento::registerMallocOverflowSecurityChecker(CheckerManager &mgr) {
339 mgr.registerChecker<MallocOverflowSecurityChecker>();
Represents a function declaration or definition.
EvaluatedExprVisitor - This class visits 'Expr *'s.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
ElementList::iterator iterator
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
Decl - This represents one declaration (or definition), e.g.
const char *const UnixAPI
static bool isAssignmentOp(Opcode Opc)
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.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
APValue Val
Val - This is the value the expression can be folded to.
A builtin binary operation expression such as "x + y" or "x <= y".
CFGBlockListTy::iterator iterator
Represents a single basic block in a source-level CFG.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
This represents one expression.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
DoStmt - This represents a 'do/while' stmt.
Dataflow Directional Tag Classes.
EvalResult is a struct with detailed info about an evaluated expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
static bool EvaluatesToZero(APSInt &Val, BinaryOperatorKind op)
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
Create the location for the operator of the binary expression.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
WhileStmt - This represents a 'while' stmt.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
A reference to a declared variable, function, enum, etc.
static bool isComparisonOp(Opcode Opc)