25 #include "llvm/ADT/APSInt.h" 26 #include "llvm/ADT/SmallVector.h" 29 using namespace clang;
34 struct MallocOverflowCheck {
40 : mulop(m), variable(v), maxVal(
std::move(val)) {}
43 class MallocOverflowSecurityChecker :
public Checker<check::ASTCodeBody> {
45 void checkASTCodeBody(
const Decl *D, AnalysisManager &mgr,
46 BugReporter &BR)
const;
48 void CheckMallocArgument(
52 void OutputPossibleOverflows(
54 const Decl *D, BugReporter &BR, AnalysisManager &mgr)
const;
61 return (op == BO_Mul) && (Val == 0);
64 void MallocOverflowSecurityChecker::CheckMallocArgument(
66 const Expr *TheArgument,
74 const Expr *e = TheArgument;
84 if (mulop ==
nullptr && opc == BO_Mul)
86 if (opc != BO_Mul && opc != BO_Add && opc != BO_Sub && opc != BO_Shl)
89 const Expr *lhs = binop->getLHS();
90 const Expr *rhs = binop->getRHS();
96 }
else if ((opc == BO_Add || opc == BO_Mul) &&
105 else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e))
111 if (mulop ==
nullptr)
120 PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e, maxVal));
125 class CheckOverflowOps :
131 theVecType &toScanFor;
134 bool isIntZeroExpr(
const Expr *E)
const {
148 template <
typename T1>
149 void Erase(
const T1 *DR,
150 llvm::function_ref<
bool(
const MallocOverflowCheck &)> Pred) {
151 auto P = [DR, Pred](
const MallocOverflowCheck &Check) {
152 if (
const auto *CheckDR = dyn_cast<T1>(Check.variable))
153 return getDecl(CheckDR) == getDecl(DR) && Pred(Check);
156 toScanFor.erase(std::remove_if(toScanFor.begin(), toScanFor.end(),
P),
160 void CheckExpr(
const Expr *E_p) {
161 auto PredTrue = [](
const MallocOverflowCheck &) {
return true; };
163 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
164 Erase<DeclRefExpr>(DR, PredTrue);
165 else if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
166 Erase<MemberExpr>(ME, PredTrue);
176 bool assignKnown =
false;
177 bool numeratorKnown =
false, denomKnown =
false;
191 if (BOp->getOpcode() == BO_Div) {
200 numeratorKnown =
true;
203 if (!assignKnown && !denomKnown)
205 auto denomExtVal = denomVal.getExtValue();
214 auto pred = [assignKnown, numeratorKnown,
215 denomExtVal](
const MallocOverflowCheck &Check) {
216 return assignKnown ||
217 (numeratorKnown && (denomExtVal >= Check.maxVal.getExtValue()));
220 if (
const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
221 Erase<DeclRefExpr>(DR, pred);
222 else if (
const auto *ME = dyn_cast<MemberExpr>(E))
223 Erase<MemberExpr>(ME, pred);
233 if (!isIntZeroExpr(lhs) && !isIntZeroExpr(rhs)) {
239 CheckAssignmentExpr(E);
246 return this->Visit(S->
getBody());
248 void VisitForStmt(
ForStmt *S) {
249 return this->Visit(S->
getBody());
251 void VisitDoStmt(
DoStmt *S) {
252 return this->Visit(S->
getBody());
257 toScanFor(v), Context(ctx)
269 void MallocOverflowSecurityChecker::OutputPossibleOverflows(
271 const Decl *D, BugReporter &BR, AnalysisManager &mgr)
const {
273 if (PossibleMallocOverflows.empty())
277 CheckOverflowOps c(PossibleMallocOverflows, BR.getContext());
278 c.Visit(mgr.getAnalysisDeclContext(D)->getBody());
281 for (CheckOverflowOps::theVecType::iterator
282 i = PossibleMallocOverflows.begin(),
283 e = PossibleMallocOverflows.end();
288 "the computation of the size of the memory allocation may overflow",
290 BR.getSourceManager()),
291 i->mulop->getSourceRange());
295 void MallocOverflowSecurityChecker::checkASTCodeBody(
const Decl *D,
296 AnalysisManager &mgr,
297 BugReporter &BR)
const {
299 CFG *cfg = mgr.getCFG(D);
311 if (
const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) {
323 if (FnInfo->
isStr (
"malloc") || FnInfo->
isStr (
"_MALLOC")) {
324 if (TheCall->getNumArgs() == 1)
325 CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0),
326 mgr.getASTContext());
333 OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr);
336 void ento::registerMallocOverflowSecurityChecker(CheckerManager &mgr) {
337 mgr.registerChecker<MallocOverflowSecurityChecker>();
340 bool ento::shouldRegisterMallocOverflowSecurityChecker(
const LangOptions &LO) {
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
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 ...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
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.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
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)