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: NumberObjectConversionChecker.cpp
//===- NumberObjectConversionChecker.cpp -------------------------*- 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 NumberObjectConversionChecker, which checks for a // particular common mistake when dealing with numbers represented as objects // passed around by pointers. Namely, the language allows to reinterpret the // pointer as a number directly, often without throwing any warnings, // but in most cases the result of such conversion is clearly unexpected, // as pointer value, rather than number value represented by the pointee object, // becomes the result of such operation. // // Currently the checker supports the Objective-C NSNumber class, // and the OSBoolean class found in macOS low-level code; the latter // can only hold boolean values. // // This checker has an option "Pedantic" (boolean), which enables detection of // more conversion patterns (which are most likely more harmless, and therefore // are more likely to produce false positives) - disabled by default, // enabled with `-analyzer-config osx.NumberObjectConversion:Pedantic=true'. // //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/APSInt.h" using namespace clang; using namespace ento; using namespace ast_matchers; namespace { class NumberObjectConversionChecker : public Checker<check::ASTCodeBody> { public: bool Pedantic; void checkASTCodeBody(const Decl *D, AnalysisManager &AM, BugReporter &BR) const; }; class Callback : public MatchFinder::MatchCallback { const NumberObjectConversionChecker *C; BugReporter &BR; AnalysisDeclContext *ADC; public: Callback(const NumberObjectConversionChecker *C, BugReporter &BR, AnalysisDeclContext *ADC) : C(C), BR(BR), ADC(ADC) {} void run(const MatchFinder::MatchResult &Result) override; }; } // end of anonymous namespace void Callback::run(const MatchFinder::MatchResult &Result) { bool IsPedanticMatch = (Result.Nodes.getNodeAs<Stmt>("pedantic") != nullptr); if (IsPedanticMatch && !C->Pedantic) return; ASTContext &ACtx = ADC->getASTContext(); if (const Expr *CheckIfNull = Result.Nodes.getNodeAs<Expr>("check_if_null")) { // Unless the macro indicates that the intended type is clearly not // a pointer type, we should avoid warning on comparing pointers // to zero literals in non-pedantic mode. // FIXME: Introduce an AST matcher to implement the macro-related logic? bool MacroIndicatesWeShouldSkipTheCheck = false; SourceLocation Loc = CheckIfNull->getBeginLoc(); if (Loc.isMacroID()) { StringRef MacroName = Lexer::getImmediateMacroName( Loc, ACtx.getSourceManager(), ACtx.getLangOpts()); if (MacroName == "NULL" || MacroName == "nil") return; if (MacroName == "YES" || MacroName == "NO") MacroIndicatesWeShouldSkipTheCheck = true; } if (!MacroIndicatesWeShouldSkipTheCheck) { Expr::EvalResult EVResult; if (CheckIfNull->IgnoreParenCasts()->EvaluateAsInt( EVResult, ACtx, Expr::SE_AllowSideEffects)) { llvm::APSInt Result = EVResult.Val.getInt(); if (Result == 0) { if (!C->Pedantic) return; IsPedanticMatch = true; } } } } const Stmt *Conv = Result.Nodes.getNodeAs<Stmt>("conv"); assert(Conv); const Expr *ConvertedCObject = Result.Nodes.getNodeAs<Expr>("c_object"); const Expr *ConvertedCppObject = Result.Nodes.getNodeAs<Expr>("cpp_object"); const Expr *ConvertedObjCObject = Result.Nodes.getNodeAs<Expr>("objc_object"); bool IsCpp = (ConvertedCppObject != nullptr); bool IsObjC = (ConvertedObjCObject != nullptr); const Expr *Obj = IsObjC ? ConvertedObjCObject : IsCpp ? ConvertedCppObject : ConvertedCObject; assert(Obj); bool IsComparison = (Result.Nodes.getNodeAs<Stmt>("comparison") != nullptr); bool IsOSNumber = (Result.Nodes.getNodeAs<Decl>("osnumber") != nullptr); bool IsInteger = (Result.Nodes.getNodeAs<QualType>("int_type") != nullptr); bool IsObjCBool = (Result.Nodes.getNodeAs<QualType>("objc_bool_type") != nullptr); bool IsCppBool = (Result.Nodes.getNodeAs<QualType>("cpp_bool_type") != nullptr); llvm::SmallString<64> Msg; llvm::raw_svector_ostream OS(Msg); // Remove ObjC ARC qualifiers. QualType ObjT = Obj->getType().getUnqualifiedType(); // Remove consts from pointers. if (IsCpp) { assert(ObjT.getCanonicalType()->isPointerType()); ObjT = ACtx.getPointerType( ObjT->getPointeeType().getCanonicalType().getUnqualifiedType()); } if (IsComparison) OS << "Comparing "; else OS << "Converting "; OS << "a pointer value of type '" << ObjT.getAsString() << "' to a "; std::string EuphemismForPlain = "primitive"; std::string SuggestedApi = IsObjC ? (IsInteger ? "" : "-boolValue") : IsCpp ? (IsOSNumber ? "" : "getValue()") : "CFNumberGetValue()"; if (SuggestedApi.empty()) { // A generic message if we're not sure what API should be called. // FIXME: Pattern-match the integer type to make a better guess? SuggestedApi = "a method on '" + ObjT.getAsString() + "' to get the scalar value"; // "scalar" is not quite correct or common, but some documentation uses it // when describing object methods we suggest. For consistency, we use // "scalar" in the whole sentence when we need to use this word in at least // one place, otherwise we use "primitive". EuphemismForPlain = "scalar"; } if (IsInteger) OS << EuphemismForPlain << " integer value"; else if (IsObjCBool) OS << EuphemismForPlain << " BOOL value"; else if (IsCppBool) OS << EuphemismForPlain << " bool value"; else // Branch condition? OS << EuphemismForPlain << " boolean value"; if (IsPedanticMatch) OS << "; instead, either compare the pointer to " << (IsObjC ? "nil" : IsCpp ? "nullptr" : "NULL") << " or "; else OS << "; did you mean to "; if (IsComparison) OS << "compare the result of calling " << SuggestedApi; else OS << "call " << SuggestedApi; if (!IsPedanticMatch) OS << "?"; BR.EmitBasicReport( ADC->getDecl(), C, "Suspicious number object conversion", "Logic error", OS.str(), PathDiagnosticLocation::createBegin(Obj, BR.getSourceManager(), ADC), Conv->getSourceRange()); } void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D, AnalysisManager &AM, BugReporter &BR) const { // Currently this matches CoreFoundation opaque pointer typedefs. auto CSuspiciousNumberObjectExprM = expr(ignoringParenImpCasts( expr(hasType( typedefType(hasDeclaration(anyOf( typedefDecl(hasName("CFNumberRef")), typedefDecl(hasName("CFBooleanRef"))))))) .bind("c_object"))); // Currently this matches XNU kernel number-object pointers. auto CppSuspiciousNumberObjectExprM = expr(ignoringParenImpCasts( expr(hasType(hasCanonicalType( pointerType(pointee(hasCanonicalType( recordType(hasDeclaration( anyOf( cxxRecordDecl(hasName("OSBoolean")), cxxRecordDecl(hasName("OSNumber")) .bind("osnumber")))))))))) .bind("cpp_object"))); // Currently this matches NeXTSTEP number objects. auto ObjCSuspiciousNumberObjectExprM = expr(ignoringParenImpCasts( expr(hasType(hasCanonicalType( objcObjectPointerType(pointee( qualType(hasCanonicalType( qualType(hasDeclaration( objcInterfaceDecl(hasName("NSNumber"))))))))))) .bind("objc_object"))); auto SuspiciousNumberObjectExprM = anyOf( CSuspiciousNumberObjectExprM, CppSuspiciousNumberObjectExprM, ObjCSuspiciousNumberObjectExprM); // Useful for predicates like "Unless we've seen the same object elsewhere". auto AnotherSuspiciousNumberObjectExprM = expr(anyOf( equalsBoundNode("c_object"), equalsBoundNode("objc_object"), equalsBoundNode("cpp_object"))); // The .bind here is in order to compose the error message more accurately. auto ObjCSuspiciousScalarBooleanTypeM = qualType(typedefType(hasDeclaration( typedefDecl(hasName("BOOL"))))).bind("objc_bool_type"); // The .bind here is in order to compose the error message more accurately. auto SuspiciousScalarBooleanTypeM = qualType(anyOf(qualType(booleanType()).bind("cpp_bool_type"), ObjCSuspiciousScalarBooleanTypeM)); // The .bind here is in order to compose the error message more accurately. // Also avoid intptr_t and uintptr_t because they were specifically created // for storing pointers. auto SuspiciousScalarNumberTypeM = qualType(hasCanonicalType(isInteger()), unless(typedefType(hasDeclaration( typedefDecl(matchesName("^::u?intptr_t$")))))) .bind("int_type"); auto SuspiciousScalarTypeM = qualType(anyOf(SuspiciousScalarBooleanTypeM, SuspiciousScalarNumberTypeM)); auto SuspiciousScalarExprM = expr(ignoringParenImpCasts(expr(hasType(SuspiciousScalarTypeM)))); auto ConversionThroughAssignmentM = binaryOperator(allOf(hasOperatorName("="), hasLHS(SuspiciousScalarExprM), hasRHS(SuspiciousNumberObjectExprM))); auto ConversionThroughBranchingM = ifStmt(allOf( hasCondition(SuspiciousNumberObjectExprM), unless(hasConditionVariableStatement(declStmt()) ))).bind("pedantic"); auto ConversionThroughCallM = callExpr(hasAnyArgument(allOf(hasType(SuspiciousScalarTypeM), ignoringParenImpCasts( SuspiciousNumberObjectExprM)))); // We bind "check_if_null" to modify the warning message // in case it was intended to compare a pointer to 0 with a relatively-ok // construct "x == 0" or "x != 0". auto ConversionThroughEquivalenceM = binaryOperator(allOf(anyOf(hasOperatorName("=="), hasOperatorName("!=")), hasEitherOperand(SuspiciousNumberObjectExprM), hasEitherOperand(SuspiciousScalarExprM .bind("check_if_null")))) .bind("comparison"); auto ConversionThroughComparisonM = binaryOperator(allOf(anyOf(hasOperatorName(">="), hasOperatorName(">"), hasOperatorName("<="), hasOperatorName("<")), hasEitherOperand(SuspiciousNumberObjectExprM), hasEitherOperand(SuspiciousScalarExprM))) .bind("comparison"); auto ConversionThroughConditionalOperatorM = conditionalOperator(allOf( hasCondition(SuspiciousNumberObjectExprM), unless(hasTrueExpression( hasDescendant(AnotherSuspiciousNumberObjectExprM))), unless(hasFalseExpression( hasDescendant(AnotherSuspiciousNumberObjectExprM))))) .bind("pedantic"); auto ConversionThroughExclamationMarkM = unaryOperator(allOf(hasOperatorName("!"), has(expr(SuspiciousNumberObjectExprM)))) .bind("pedantic"); auto ConversionThroughExplicitBooleanCastM = explicitCastExpr(allOf(hasType(SuspiciousScalarBooleanTypeM), has(expr(SuspiciousNumberObjectExprM)))); auto ConversionThroughExplicitNumberCastM = explicitCastExpr(allOf(hasType(SuspiciousScalarNumberTypeM), has(expr(SuspiciousNumberObjectExprM)))); auto ConversionThroughInitializerM = declStmt(hasSingleDecl( varDecl(hasType(SuspiciousScalarTypeM), hasInitializer(SuspiciousNumberObjectExprM)))); auto FinalM = stmt(anyOf(ConversionThroughAssignmentM, ConversionThroughBranchingM, ConversionThroughCallM, ConversionThroughComparisonM, ConversionThroughConditionalOperatorM, ConversionThroughEquivalenceM, ConversionThroughExclamationMarkM, ConversionThroughExplicitBooleanCastM, ConversionThroughExplicitNumberCastM, ConversionThroughInitializerM)).bind("conv"); MatchFinder F; Callback CB(this, BR, AM.getAnalysisDeclContext(D)); F.addMatcher(traverse(TK_AsIs, stmt(forEachDescendant(FinalM))), &CB); F.match(*D->getBody(), AM.getASTContext()); } void ento::registerNumberObjectConversionChecker(CheckerManager &Mgr) { NumberObjectConversionChecker *Chk = Mgr.registerChecker<NumberObjectConversionChecker>(); Chk->Pedantic = Mgr.getAnalyzerOptions().getCheckerBooleanOption(Chk, "Pedantic"); } bool ento::shouldRegisterNumberObjectConversionChecker(const CheckerManager &mgr) { return true; }
Upload File
Create Folder