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: CheckPlacementNew.cpp
//==- CheckPlacementNew.cpp - Check for placement new operation --*- 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 file defines a check for misuse of the default placement new operator. // //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h" #include "llvm/Support/FormatVariadic.h" using namespace clang; using namespace ento; namespace { class PlacementNewChecker : public Checker<check::PreStmt<CXXNewExpr>> { public: void checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const; private: bool checkPlaceCapacityIsSufficient(const CXXNewExpr *NE, CheckerContext &C) const; bool checkPlaceIsAlignedProperly(const CXXNewExpr *NE, CheckerContext &C) const; // Returns the size of the target in a placement new expression. // E.g. in "new (&s) long" it returns the size of `long`. SVal getExtentSizeOfNewTarget(const CXXNewExpr *NE, CheckerContext &C, bool &IsArray) const; // Returns the size of the place in a placement new expression. // E.g. in "new (&s) long" it returns the size of `s`. SVal getExtentSizeOfPlace(const CXXNewExpr *NE, CheckerContext &C) const; void emitBadAlignReport(const Expr *P, CheckerContext &C, unsigned AllocatedTAlign, unsigned StorageTAlign) const; unsigned getStorageAlign(CheckerContext &C, const ValueDecl *VD) const; void checkElementRegionAlign(const ElementRegion *R, CheckerContext &C, const Expr *P, unsigned AllocatedTAlign) const; void checkFieldRegionAlign(const FieldRegion *R, CheckerContext &C, const Expr *P, unsigned AllocatedTAlign) const; bool isVarRegionAlignedProperly(const VarRegion *R, CheckerContext &C, const Expr *P, unsigned AllocatedTAlign) const; BugType SBT{this, "Insufficient storage for placement new", categories::MemoryError}; BugType ABT{this, "Bad align storage for placement new", categories::MemoryError}; }; } // namespace SVal PlacementNewChecker::getExtentSizeOfPlace(const CXXNewExpr *NE, CheckerContext &C) const { const Expr *Place = NE->getPlacementArg(0); return getDynamicSizeWithOffset(C.getState(), C.getSVal(Place)); } SVal PlacementNewChecker::getExtentSizeOfNewTarget(const CXXNewExpr *NE, CheckerContext &C, bool &IsArray) const { ProgramStateRef State = C.getState(); SValBuilder &SvalBuilder = C.getSValBuilder(); QualType ElementType = NE->getAllocatedType(); ASTContext &AstContext = C.getASTContext(); CharUnits TypeSize = AstContext.getTypeSizeInChars(ElementType); IsArray = false; if (NE->isArray()) { IsArray = true; const Expr *SizeExpr = *NE->getArraySize(); SVal ElementCount = C.getSVal(SizeExpr); if (auto ElementCountNL = ElementCount.getAs<NonLoc>()) { // size in Bytes = ElementCountNL * TypeSize return SvalBuilder.evalBinOp( State, BO_Mul, *ElementCountNL, SvalBuilder.makeArrayIndex(TypeSize.getQuantity()), SvalBuilder.getArrayIndexType()); } } else { // Create a concrete int whose size in bits and signedness is equal to // ArrayIndexType. llvm::APInt I(AstContext.getTypeSizeInChars(SvalBuilder.getArrayIndexType()) .getQuantity() * C.getASTContext().getCharWidth(), TypeSize.getQuantity()); return SvalBuilder.makeArrayIndex(I.getZExtValue()); } return UnknownVal(); } bool PlacementNewChecker::checkPlaceCapacityIsSufficient( const CXXNewExpr *NE, CheckerContext &C) const { bool IsArrayTypeAllocated; SVal SizeOfTarget = getExtentSizeOfNewTarget(NE, C, IsArrayTypeAllocated); SVal SizeOfPlace = getExtentSizeOfPlace(NE, C); const auto SizeOfTargetCI = SizeOfTarget.getAs<nonloc::ConcreteInt>(); if (!SizeOfTargetCI) return true; const auto SizeOfPlaceCI = SizeOfPlace.getAs<nonloc::ConcreteInt>(); if (!SizeOfPlaceCI) return true; if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue()) || (IsArrayTypeAllocated && SizeOfPlaceCI->getValue() >= SizeOfTargetCI->getValue())) { if (ExplodedNode *N = C.generateErrorNode(C.getState())) { std::string Msg; // TODO: use clang constant if (IsArrayTypeAllocated && SizeOfPlaceCI->getValue() > SizeOfTargetCI->getValue()) Msg = std::string(llvm::formatv( "{0} bytes is possibly not enough for array allocation which " "requires {1} bytes. Current overhead requires the size of {2} " "bytes", SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue(), SizeOfPlaceCI->getValue() - SizeOfTargetCI->getValue())); else if (IsArrayTypeAllocated && SizeOfPlaceCI->getValue() == SizeOfTargetCI->getValue()) Msg = std::string(llvm::formatv( "Storage provided to placement new is only {0} bytes, " "whereas the allocated array type requires more space for " "internal needs", SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue())); else Msg = std::string(llvm::formatv( "Storage provided to placement new is only {0} bytes, " "whereas the allocated type requires {1} bytes", SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue())); auto R = std::make_unique<PathSensitiveBugReport>(SBT, Msg, N); bugreporter::trackExpressionValue(N, NE->getPlacementArg(0), *R); C.emitReport(std::move(R)); return false; } } return true; } void PlacementNewChecker::emitBadAlignReport(const Expr *P, CheckerContext &C, unsigned AllocatedTAlign, unsigned StorageTAlign) const { ProgramStateRef State = C.getState(); if (ExplodedNode *N = C.generateErrorNode(State)) { std::string Msg(llvm::formatv("Storage type is aligned to {0} bytes but " "allocated type is aligned to {1} bytes", StorageTAlign, AllocatedTAlign)); auto R = std::make_unique<PathSensitiveBugReport>(ABT, Msg, N); bugreporter::trackExpressionValue(N, P, *R); C.emitReport(std::move(R)); } } unsigned PlacementNewChecker::getStorageAlign(CheckerContext &C, const ValueDecl *VD) const { unsigned StorageTAlign = C.getASTContext().getTypeAlign(VD->getType()); if (unsigned SpecifiedAlignment = VD->getMaxAlignment()) StorageTAlign = SpecifiedAlignment; return StorageTAlign / C.getASTContext().getCharWidth(); } void PlacementNewChecker::checkElementRegionAlign( const ElementRegion *R, CheckerContext &C, const Expr *P, unsigned AllocatedTAlign) const { auto IsBaseRegionAlignedProperly = [this, R, &C, P, AllocatedTAlign]() -> bool { // Unwind nested ElementRegion`s to get the type. const MemRegion *SuperRegion = R; while (true) { if (SuperRegion->getKind() == MemRegion::ElementRegionKind) { SuperRegion = cast<SubRegion>(SuperRegion)->getSuperRegion(); continue; } break; } const DeclRegion *TheElementDeclRegion = SuperRegion->getAs<DeclRegion>(); if (!TheElementDeclRegion) return false; const DeclRegion *BaseDeclRegion = R->getBaseRegion()->getAs<DeclRegion>(); if (!BaseDeclRegion) return false; unsigned BaseRegionAlign = 0; // We must use alignment TheElementDeclRegion if it has its own alignment // specifier if (TheElementDeclRegion->getDecl()->getMaxAlignment()) BaseRegionAlign = getStorageAlign(C, TheElementDeclRegion->getDecl()); else BaseRegionAlign = getStorageAlign(C, BaseDeclRegion->getDecl()); if (AllocatedTAlign > BaseRegionAlign) { emitBadAlignReport(P, C, AllocatedTAlign, BaseRegionAlign); return false; } return true; }; auto CheckElementRegionOffset = [this, R, &C, P, AllocatedTAlign]() -> void { RegionOffset TheOffsetRegion = R->getAsOffset(); if (TheOffsetRegion.hasSymbolicOffset()) return; unsigned Offset = TheOffsetRegion.getOffset() / C.getASTContext().getCharWidth(); unsigned AddressAlign = Offset % AllocatedTAlign; if (AddressAlign != 0) { emitBadAlignReport(P, C, AllocatedTAlign, AddressAlign); return; } }; if (IsBaseRegionAlignedProperly()) { CheckElementRegionOffset(); } } void PlacementNewChecker::checkFieldRegionAlign( const FieldRegion *R, CheckerContext &C, const Expr *P, unsigned AllocatedTAlign) const { const MemRegion *BaseRegion = R->getBaseRegion(); if (!BaseRegion) return; if (const VarRegion *TheVarRegion = BaseRegion->getAs<VarRegion>()) { if (isVarRegionAlignedProperly(TheVarRegion, C, P, AllocatedTAlign)) { // We've checked type align but, unless FieldRegion // offset is zero, we also need to check its own // align. RegionOffset Offset = R->getAsOffset(); if (Offset.hasSymbolicOffset()) return; int64_t OffsetValue = Offset.getOffset() / C.getASTContext().getCharWidth(); unsigned AddressAlign = OffsetValue % AllocatedTAlign; if (AddressAlign != 0) emitBadAlignReport(P, C, AllocatedTAlign, AddressAlign); } } } bool PlacementNewChecker::isVarRegionAlignedProperly( const VarRegion *R, CheckerContext &C, const Expr *P, unsigned AllocatedTAlign) const { const VarDecl *TheVarDecl = R->getDecl(); unsigned StorageTAlign = getStorageAlign(C, TheVarDecl); if (AllocatedTAlign > StorageTAlign) { emitBadAlignReport(P, C, AllocatedTAlign, StorageTAlign); return false; } return true; } bool PlacementNewChecker::checkPlaceIsAlignedProperly(const CXXNewExpr *NE, CheckerContext &C) const { const Expr *Place = NE->getPlacementArg(0); QualType AllocatedT = NE->getAllocatedType(); unsigned AllocatedTAlign = C.getASTContext().getTypeAlign(AllocatedT) / C.getASTContext().getCharWidth(); SVal PlaceVal = C.getSVal(Place); if (const MemRegion *MRegion = PlaceVal.getAsRegion()) { if (const ElementRegion *TheElementRegion = MRegion->getAs<ElementRegion>()) checkElementRegionAlign(TheElementRegion, C, Place, AllocatedTAlign); else if (const FieldRegion *TheFieldRegion = MRegion->getAs<FieldRegion>()) checkFieldRegionAlign(TheFieldRegion, C, Place, AllocatedTAlign); else if (const VarRegion *TheVarRegion = MRegion->getAs<VarRegion>()) isVarRegionAlignedProperly(TheVarRegion, C, Place, AllocatedTAlign); } return true; } void PlacementNewChecker::checkPreStmt(const CXXNewExpr *NE, CheckerContext &C) const { // Check only the default placement new. if (!NE->getOperatorNew()->isReservedGlobalPlacementOperator()) return; if (NE->getNumPlacementArgs() == 0) return; if (!checkPlaceCapacityIsSufficient(NE, C)) return; checkPlaceIsAlignedProperly(NE, C); } void ento::registerPlacementNewChecker(CheckerManager &mgr) { mgr.registerChecker<PlacementNewChecker>(); } bool ento::shouldRegisterPlacementNewChecker(const CheckerManager &mgr) { return true; }
Upload File
Create Folder