003 File Manager
Current Path:
/usr/src/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers
usr
/
src
/
contrib
/
llvm-project
/
clang
/
lib
/
StaticAnalyzer
/
Checkers
/
📁
..
📄
AllocationState.h
(1.41 KB)
📄
AnalysisOrderChecker.cpp
(8.62 KB)
📄
AnalyzerStatsChecker.cpp
(5.04 KB)
📄
ArrayBoundChecker.cpp
(3.22 KB)
📄
ArrayBoundCheckerV2.cpp
(13.07 KB)
📄
BasicObjCFoundationChecks.cpp
(43.82 KB)
📄
BlockInCriticalSectionChecker.cpp
(6.69 KB)
📄
BoolAssignmentChecker.cpp
(3.45 KB)
📄
BuiltinFunctionChecker.cpp
(5 KB)
📄
CStringChecker.cpp
(93.24 KB)
📄
CStringSyntaxChecker.cpp
(9.8 KB)
📄
CXXSelfAssignmentChecker.cpp
(3.08 KB)
📄
CallAndMessageChecker.cpp
(26.57 KB)
📄
CastSizeChecker.cpp
(4.96 KB)
📄
CastToStructChecker.cpp
(4.43 KB)
📄
CastValueChecker.cpp
(19.65 KB)
📄
CheckObjCDealloc.cpp
(37.83 KB)
📄
CheckObjCInstMethSignature.cpp
(4.8 KB)
📄
CheckPlacementNew.cpp
(11.91 KB)
📄
CheckSecuritySyntaxOnly.cpp
(38.79 KB)
📄
CheckSizeofPointer.cpp
(3.16 KB)
📄
CheckerDocumentation.cpp
(14.64 KB)
📄
ChrootChecker.cpp
(4.88 KB)
📄
CloneChecker.cpp
(8.28 KB)
📄
ContainerModeling.cpp
(39.85 KB)
📄
ConversionChecker.cpp
(7.11 KB)
📄
DeadStoresChecker.cpp
(17.82 KB)
📄
DebugCheckers.cpp
(10.41 KB)
📄
DebugContainerModeling.cpp
(4.94 KB)
📄
DebugIteratorModeling.cpp
(5.15 KB)
📄
DeleteWithNonVirtualDtorChecker.cpp
(5.35 KB)
📄
DereferenceChecker.cpp
(10.54 KB)
📄
DirectIvarAssignment.cpp
(8.02 KB)
📄
DivZeroChecker.cpp
(3.42 KB)
📄
DynamicTypeChecker.cpp
(7.31 KB)
📄
DynamicTypePropagation.cpp
(42.11 KB)
📄
EnumCastOutOfRangeChecker.cpp
(5.75 KB)
📄
ExprInspectionChecker.cpp
(15.6 KB)
📄
FixedAddressChecker.cpp
(2.33 KB)
📄
FuchsiaHandleChecker.cpp
(23.1 KB)
📄
GCDAntipatternChecker.cpp
(7.85 KB)
📄
GTestChecker.cpp
(10.52 KB)
📄
GenericTaintChecker.cpp
(34.31 KB)
📄
IdenticalExprChecker.cpp
(18.88 KB)
📄
InnerPointerChecker.cpp
(11.54 KB)
📄
InterCheckerAPI.h
(1.09 KB)
📄
InvalidatedIteratorChecker.cpp
(4.93 KB)
📄
Iterator.cpp
(10.62 KB)
📄
Iterator.h
(6.32 KB)
📄
IteratorModeling.cpp
(31.33 KB)
📄
IteratorRangeChecker.cpp
(12.64 KB)
📄
IvarInvalidationChecker.cpp
(27.63 KB)
📄
LLVMConventionsChecker.cpp
(9.9 KB)
📄
LocalizationChecker.cpp
(52.38 KB)
📄
MIGChecker.cpp
(11.3 KB)
📁
MPI-Checker
📄
MacOSKeychainAPIChecker.cpp
(25.21 KB)
📄
MacOSXAPIChecker.cpp
(6.61 KB)
📄
MallocChecker.cpp
(127.38 KB)
📄
MallocOverflowSecurityChecker.cpp
(11.91 KB)
📄
MallocSizeofChecker.cpp
(8.03 KB)
📄
MismatchedIteratorChecker.cpp
(11.01 KB)
📄
MmapWriteExecChecker.cpp
(3.22 KB)
📄
Move.h
(1.07 KB)
📄
MoveChecker.cpp
(27 KB)
📄
NSAutoreleasePoolChecker.cpp
(2.93 KB)
📄
NSErrorChecker.cpp
(10.6 KB)
📄
NoReturnFunctionChecker.cpp
(5.48 KB)
📄
NonNullParamChecker.cpp
(11.22 KB)
📄
NonnullGlobalConstantsChecker.cpp
(5.09 KB)
📄
NullabilityChecker.cpp
(46.95 KB)
📄
NumberObjectConversionChecker.cpp
(13.69 KB)
📄
OSObjectCStyleCast.cpp
(3.14 KB)
📄
ObjCAtSyncChecker.cpp
(3.34 KB)
📄
ObjCAutoreleaseWriteChecker.cpp
(8.62 KB)
📄
ObjCContainersASTChecker.cpp
(5.5 KB)
📄
ObjCContainersChecker.cpp
(6.71 KB)
📄
ObjCMissingSuperCallChecker.cpp
(9.23 KB)
📄
ObjCPropertyChecker.cpp
(3.03 KB)
📄
ObjCSelfInitChecker.cpp
(16.21 KB)
📄
ObjCSuperDeallocChecker.cpp
(9.33 KB)
📄
ObjCUnusedIVarsChecker.cpp
(6.01 KB)
📄
PaddingChecker.cpp
(14.26 KB)
📄
PointerArithChecker.cpp
(12.18 KB)
📄
PointerIterationChecker.cpp
(3.79 KB)
📄
PointerSortingChecker.cpp
(4.5 KB)
📄
PointerSubChecker.cpp
(2.56 KB)
📄
PthreadLockChecker.cpp
(28.42 KB)
📁
RetainCountChecker
📄
ReturnPointerRangeChecker.cpp
(3.39 KB)
📄
ReturnUndefChecker.cpp
(4.1 KB)
📄
ReturnValueChecker.cpp
(5.79 KB)
📄
RunLoopAutoreleaseLeakChecker.cpp
(7.2 KB)
📄
STLAlgorithmModeling.cpp
(7 KB)
📄
SimpleStreamChecker.cpp
(9.43 KB)
📄
SmartPtr.h
(1.17 KB)
📄
SmartPtrChecker.cpp
(2.68 KB)
📄
SmartPtrModeling.cpp
(8.05 KB)
📄
StackAddrEscapeChecker.cpp
(15 KB)
📄
StdLibraryFunctionsChecker.cpp
(74.86 KB)
📄
StreamChecker.cpp
(37.36 KB)
📄
Taint.cpp
(9.04 KB)
📄
Taint.h
(4.19 KB)
📄
TaintTesterChecker.cpp
(2.17 KB)
📄
TestAfterDivZeroChecker.cpp
(8.19 KB)
📄
TraversalChecker.cpp
(4.38 KB)
📄
TrustNonnullChecker.cpp
(9.12 KB)
📄
UndefBranchChecker.cpp
(3.82 KB)
📄
UndefCapturedBlockVarChecker.cpp
(3.64 KB)
📄
UndefResultChecker.cpp
(7.19 KB)
📄
UndefinedArraySubscriptChecker.cpp
(2.36 KB)
📄
UndefinedAssignmentChecker.cpp
(3.74 KB)
📁
UninitializedObject
📄
UnixAPIChecker.cpp
(18.05 KB)
📄
UnreachableCodeChecker.cpp
(9.59 KB)
📄
VLASizeChecker.cpp
(10.95 KB)
📄
ValistChecker.cpp
(15.65 KB)
📄
VforkChecker.cpp
(7.67 KB)
📄
VirtualCallChecker.cpp
(8.11 KB)
📁
WebKit
📄
Yaml.h
(2.06 KB)
📁
cert
Editing: MallocOverflowSecurityChecker.cpp
// MallocOverflowSecurityChecker.cpp - Check for malloc overflows -*- C++ -*-=// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This checker detects a common memory allocation security flaw. // Suppose 'unsigned int n' comes from an untrusted source. If the // code looks like 'malloc (n * 4)', and an attacker can make 'n' be // say MAX_UINT/4+2, then instead of allocating the correct 'n' 4-byte // elements, this will actually allocate only two because of overflow. // Then when the rest of the program attempts to store values past the // second element, these values will actually overwrite other items in // the heap, probably allowing the attacker to execute arbitrary code. // //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include <utility> using namespace clang; using namespace ento; using llvm::APSInt; namespace { struct MallocOverflowCheck { const BinaryOperator *mulop; const Expr *variable; APSInt maxVal; MallocOverflowCheck(const BinaryOperator *m, const Expr *v, APSInt val) : mulop(m), variable(v), maxVal(std::move(val)) {} }; class MallocOverflowSecurityChecker : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager &mgr, BugReporter &BR) const; void CheckMallocArgument( SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, const Expr *TheArgument, ASTContext &Context) const; void OutputPossibleOverflows( SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, const Decl *D, BugReporter &BR, AnalysisManager &mgr) const; }; } // end anonymous namespace // Return true for computations which evaluate to zero: e.g., mult by 0. static inline bool EvaluatesToZero(APSInt &Val, BinaryOperatorKind op) { return (op == BO_Mul) && (Val == 0); } void MallocOverflowSecurityChecker::CheckMallocArgument( SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, const Expr *TheArgument, ASTContext &Context) const { /* Look for a linear combination with a single variable, and at least one multiplication. Reject anything that applies to the variable: an explicit cast, conditional expression, an operation that could reduce the range of the result, or anything too complicated :-). */ const Expr *e = TheArgument; const BinaryOperator * mulop = nullptr; APSInt maxVal; for (;;) { maxVal = 0; e = e->IgnoreParenImpCasts(); if (const BinaryOperator *binop = dyn_cast<BinaryOperator>(e)) { BinaryOperatorKind opc = binop->getOpcode(); // TODO: ignore multiplications by 1, reject if multiplied by 0. if (mulop == nullptr && opc == BO_Mul) mulop = binop; if (opc != BO_Mul && opc != BO_Add && opc != BO_Sub && opc != BO_Shl) return; const Expr *lhs = binop->getLHS(); const Expr *rhs = binop->getRHS(); if (rhs->isEvaluatable(Context)) { e = lhs; maxVal = rhs->EvaluateKnownConstInt(Context); if (EvaluatesToZero(maxVal, opc)) return; } else if ((opc == BO_Add || opc == BO_Mul) && lhs->isEvaluatable(Context)) { maxVal = lhs->EvaluateKnownConstInt(Context); if (EvaluatesToZero(maxVal, opc)) return; e = rhs; } else return; } else if (isa<DeclRefExpr>(e) || isa<MemberExpr>(e)) break; else return; } if (mulop == nullptr) return; // We've found the right structure of malloc argument, now save // the data so when the body of the function is completely available // we can check for comparisons. // TODO: Could push this into the innermost scope where 'e' is // defined, rather than the whole function. PossibleMallocOverflows.push_back(MallocOverflowCheck(mulop, e, maxVal)); } namespace { // A worker class for OutputPossibleOverflows. class CheckOverflowOps : public EvaluatedExprVisitor<CheckOverflowOps> { public: typedef SmallVectorImpl<MallocOverflowCheck> theVecType; private: theVecType &toScanFor; ASTContext &Context; bool isIntZeroExpr(const Expr *E) const { if (!E->getType()->isIntegralOrEnumerationType()) return false; Expr::EvalResult Result; if (E->EvaluateAsInt(Result, Context)) return Result.Val.getInt() == 0; return false; } static const Decl *getDecl(const DeclRefExpr *DR) { return DR->getDecl(); } static const Decl *getDecl(const MemberExpr *ME) { return ME->getMemberDecl(); } template <typename T1> void Erase(const T1 *DR, llvm::function_ref<bool(const MallocOverflowCheck &)> Pred) { auto P = [DR, Pred](const MallocOverflowCheck &Check) { if (const auto *CheckDR = dyn_cast<T1>(Check.variable)) return getDecl(CheckDR) == getDecl(DR) && Pred(Check); return false; }; toScanFor.erase(std::remove_if(toScanFor.begin(), toScanFor.end(), P), toScanFor.end()); } void CheckExpr(const Expr *E_p) { auto PredTrue = [](const MallocOverflowCheck &) { return true; }; const Expr *E = E_p->IgnoreParenImpCasts(); if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) Erase<DeclRefExpr>(DR, PredTrue); else if (const auto *ME = dyn_cast<MemberExpr>(E)) { Erase<MemberExpr>(ME, PredTrue); } } // Check if the argument to malloc is assigned a value // which cannot cause an overflow. // e.g., malloc (mul * x) and, // case 1: mul = <constant value> // case 2: mul = a/b, where b > x void CheckAssignmentExpr(BinaryOperator *AssignEx) { bool assignKnown = false; bool numeratorKnown = false, denomKnown = false; APSInt denomVal; denomVal = 0; // Erase if the multiplicand was assigned a constant value. const Expr *rhs = AssignEx->getRHS(); if (rhs->isEvaluatable(Context)) assignKnown = true; // Discard the report if the multiplicand was assigned a value, // that can never overflow after multiplication. e.g., the assignment // is a division operator and the denominator is > other multiplicand. const Expr *rhse = rhs->IgnoreParenImpCasts(); if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(rhse)) { if (BOp->getOpcode() == BO_Div) { const Expr *denom = BOp->getRHS()->IgnoreParenImpCasts(); Expr::EvalResult Result; if (denom->EvaluateAsInt(Result, Context)) { denomVal = Result.Val.getInt(); denomKnown = true; } const Expr *numerator = BOp->getLHS()->IgnoreParenImpCasts(); if (numerator->isEvaluatable(Context)) numeratorKnown = true; } } if (!assignKnown && !denomKnown) return; auto denomExtVal = denomVal.getExtValue(); // Ignore negative denominator. if (denomExtVal < 0) return; const Expr *lhs = AssignEx->getLHS(); const Expr *E = lhs->IgnoreParenImpCasts(); auto pred = [assignKnown, numeratorKnown, denomExtVal](const MallocOverflowCheck &Check) { return assignKnown || (numeratorKnown && (denomExtVal >= Check.maxVal.getExtValue())); }; if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) Erase<DeclRefExpr>(DR, pred); else if (const auto *ME = dyn_cast<MemberExpr>(E)) Erase<MemberExpr>(ME, pred); } public: void VisitBinaryOperator(BinaryOperator *E) { if (E->isComparisonOp()) { const Expr * lhs = E->getLHS(); const Expr * rhs = E->getRHS(); // Ignore comparisons against zero, since they generally don't // protect against an overflow. if (!isIntZeroExpr(lhs) && !isIntZeroExpr(rhs)) { CheckExpr(lhs); CheckExpr(rhs); } } if (E->isAssignmentOp()) CheckAssignmentExpr(E); EvaluatedExprVisitor<CheckOverflowOps>::VisitBinaryOperator(E); } /* We specifically ignore loop conditions, because they're typically not error checks. */ void VisitWhileStmt(WhileStmt *S) { return this->Visit(S->getBody()); } void VisitForStmt(ForStmt *S) { return this->Visit(S->getBody()); } void VisitDoStmt(DoStmt *S) { return this->Visit(S->getBody()); } CheckOverflowOps(theVecType &v, ASTContext &ctx) : EvaluatedExprVisitor<CheckOverflowOps>(ctx), toScanFor(v), Context(ctx) { } }; } // OutputPossibleOverflows - We've found a possible overflow earlier, // now check whether Body might contain a comparison which might be // preventing the overflow. // This doesn't do flow analysis, range analysis, or points-to analysis; it's // just a dumb "is there a comparison" scan. The aim here is to // detect the most blatent cases of overflow and educate the // programmer. void MallocOverflowSecurityChecker::OutputPossibleOverflows( SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, const Decl *D, BugReporter &BR, AnalysisManager &mgr) const { // By far the most common case: nothing to check. if (PossibleMallocOverflows.empty()) return; // Delete any possible overflows which have a comparison. CheckOverflowOps c(PossibleMallocOverflows, BR.getContext()); c.Visit(mgr.getAnalysisDeclContext(D)->getBody()); // Output warnings for all overflows that are left. for (CheckOverflowOps::theVecType::iterator i = PossibleMallocOverflows.begin(), e = PossibleMallocOverflows.end(); i != e; ++i) { BR.EmitBasicReport( D, this, "malloc() size overflow", categories::UnixAPI, "the computation of the size of the memory allocation may overflow", PathDiagnosticLocation::createOperatorLoc(i->mulop, BR.getSourceManager()), i->mulop->getSourceRange()); } } void MallocOverflowSecurityChecker::checkASTCodeBody(const Decl *D, AnalysisManager &mgr, BugReporter &BR) const { CFG *cfg = mgr.getCFG(D); if (!cfg) return; // A list of variables referenced in possibly overflowing malloc operands. SmallVector<MallocOverflowCheck, 2> PossibleMallocOverflows; for (CFG::iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) { CFGBlock *block = *it; for (CFGBlock::iterator bi = block->begin(), be = block->end(); bi != be; ++bi) { if (Optional<CFGStmt> CS = bi->getAs<CFGStmt>()) { if (const CallExpr *TheCall = dyn_cast<CallExpr>(CS->getStmt())) { // Get the callee. const FunctionDecl *FD = TheCall->getDirectCallee(); if (!FD) continue; // Get the name of the callee. If it's a builtin, strip off the prefix. IdentifierInfo *FnInfo = FD->getIdentifier(); if (!FnInfo) continue; if (FnInfo->isStr ("malloc") || FnInfo->isStr ("_MALLOC")) { if (TheCall->getNumArgs() == 1) CheckMallocArgument(PossibleMallocOverflows, TheCall->getArg(0), mgr.getASTContext()); } } } } } OutputPossibleOverflows(PossibleMallocOverflows, D, BR, mgr); } void ento::registerMallocOverflowSecurityChecker(CheckerManager &mgr) { mgr.registerChecker<MallocOverflowSecurityChecker>(); } bool ento::shouldRegisterMallocOverflowSecurityChecker(const CheckerManager &mgr) { return true; }
Upload File
Create Folder