/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Utilities/StaticAnalyzers/src/FunctionChecker.cpp
249 строк
9 KB
Shahzad Malik Muzaffar
SA: Ignore system header in FunctionChecker
02 апр 2026, 16:27
02 апр 2026, 16:27
2ad0405
Код
Авторство
О чём код?
#include <clang/AST/DeclCXX.h> #include <clang/AST/Attr.h> #include <clang/AST/Decl.h> #include <clang/AST/DeclTemplate.h> #include <clang/AST/StmtVisitor.h> #include <clang/AST/ParentMap.h> #include <clang/Analysis/CFGStmtMap.h> #include <clang/Analysis/CallGraph.h> #include <llvm/Support/SaveAndRestore.h> #include <clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h> #include <clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h> #include <clang/StaticAnalyzer/Core/Checker.h> #include <clang/StaticAnalyzer/Core/BugReporter/BugReporter.h> #include <clang/StaticAnalyzer/Core/BugReporter/BugType.h> #include <llvm/ADT/SmallString.h> #include <iostream> #include <fstream> #include <iterator> #include <string> #include <algorithm> #include "FunctionChecker.h" using namespace clang; using namespace ento; using namespace llvm; namespace clangcms { class FWalker : public clang::StmtVisitor<FWalker> { const CheckerBase *Checker; clang::ento::BugReporter &BR; clang::AnalysisDeclContext *AC; public: FWalker(const CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac) : Checker(checker), BR(br), AC(ac) {} const clang::Stmt *ParentStmt(const Stmt *S) { const Stmt *P = AC->getParentMap().getParentIgnoreParens(S); if (!P) return nullptr; return P; } void VisitChildren(clang::Stmt *S); void VisitStmt(clang::Stmt *S) { VisitChildren(S); } void VisitDeclRefExpr(clang::DeclRefExpr *DRE); void ReportDeclRef(const clang::DeclRefExpr *DRE); }; void FWalker::VisitChildren(clang::Stmt *S) { for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I) if (clang::Stmt *child = *I) { Visit(child); } } void FWalker::VisitDeclRefExpr(clang::DeclRefExpr *DRE) { if (const clang::VarDecl *D = llvm::dyn_cast_or_null<clang::VarDecl>(DRE->getDecl())) { if (D && support::isSafeClassName(D->getCanonicalDecl()->getQualifiedNameAsString())) return; ReportDeclRef(DRE); } } void FWalker::ReportDeclRef(const clang::DeclRefExpr *DRE) { const clang::VarDecl *D = llvm::dyn_cast_or_null<clang::VarDecl>(DRE->getDecl()); if (!D) return; if ((D->hasAttr<CMSThreadGuardAttr>() || D->hasAttr<CMSThreadSafeAttr>()) || D->hasAttr<CMSSaAllowAttr>()) return; if (support::isSafeClassName(D->getCanonicalDecl()->getQualifiedNameAsString())) return; const auto &SM = BR.getSourceManager(); // Normalize to where the code is actually defined clang::SourceLocation loc = SM.getSpellingLoc(D->getLocation()); // Ignore anything coming from system headers (via -isystem) if (SM.isInSystemHeader(loc)) { return; } const char *sfile = SM.getPresumedLoc(loc).getFilename(); std::string fname(sfile); if (!support::isInterestingLocation(fname)) return; clang::QualType t = D->getType(); if (support::isSafeClassName(t.getCanonicalType().getAsString())) return; const Decl *PD = AC->getDecl(); std::string dname = ""; std::string sdname = ""; if (const NamedDecl *ND = llvm::dyn_cast_or_null<NamedDecl>(PD)) { sdname = support::getQualifiedName(*ND); dname = ND->getQualifiedNameAsString(); } clang::ento::PathDiagnosticLocation DLoc; if (support::isCmsLocalFile(sfile)) { if (D->getLocation().isMacroID()) DLoc = clang::ento::PathDiagnosticLocation(D->getLocation(), BR.getSourceManager()); else DLoc = clang::ento::PathDiagnosticLocation::createBegin(D, BR.getSourceManager()); } else DLoc = clang::ento::PathDiagnosticLocation::createBegin(DRE, BR.getSourceManager(), AC); std::string tname = "function-checker.txt.unsorted"; std::string vname = support::getQualifiedName(*D); std::string svname = D->getNameAsString(); if (D->getTSCSpec() == clang::ThreadStorageClassSpecifier::TSCS_thread_local) return; if (D->isStaticLocal() && !clangcms::support::isConst(t)) { std::string buf; llvm::raw_string_ostream os(buf); os << "function '" << dname << "' accesses or modifies non-const static local variable '" << svname << "'.\n"; BR.EmitBasicReport(D, #if LLVM_VERSION_MAJOR >= 21 Checker->getName(), #else Checker->getCheckerName(), #endif "non-const static local variable accessed or modified", "ThreadSafety", os.str(), DLoc); std::string ostring = "function '" + sdname + "' static variable '" + vname + "'.\n"; support::writeLog(ostring, tname); return; } if (D->isStaticDataMember() && !clangcms::support::isConst(t)) { std::string buf; llvm::raw_string_ostream os(buf); os << "function '" << dname << "' accesses or modifies non-const static member data variable '" << svname << "'.\n"; BR.EmitBasicReport(D, #if LLVM_VERSION_MAJOR >= 21 Checker->getName(), #else Checker->getCheckerName(), #endif "non-const static local variable accessed or modified", "ThreadSafety", os.str(), DLoc); std::string ostring = "function '" + sdname + "' static variable '" + vname + "'.\n"; support::writeLog(ostring, tname); return; } if (D->hasGlobalStorage() && !D->isStaticDataMember() && !D->isStaticLocal() && !clangcms::support::isConst(t)) { std::string buf; llvm::raw_string_ostream os(buf); os << "function '" << dname << "' accesses or modifies non-const global static variable '" << svname << "'.\n"; BR.EmitBasicReport(D, #if LLVM_VERSION_MAJOR >= 21 Checker->getName(), #else Checker->getCheckerName(), #endif "non-const static local variable accessed or modified", "ThreadSafety", os.str(), DLoc); std::string ostring = "function '" + sdname + "' static variable '" + vname + "'.\n"; support::writeLog(ostring, tname); return; } } void FunctionChecker::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const { if (MD->hasAttr<CMSThreadSafeAttr>() || MD->hasAttr<CMSSaAllowAttr>()) return; const char *sfile = BR.getSourceManager().getPresumedLoc(MD->getLocation()).getFilename(); if (!support::isCmsLocalFile(sfile)) return; std::string fname(sfile); if (!support::isInterestingLocation(fname)) return; if (!MD->doesThisDeclarationHaveABody()) return; FWalker walker(this, BR, mgr.getAnalysisDeclContext(MD)); walker.Visit(MD->getBody()); return; } void FunctionChecker::checkASTDecl(const FunctionDecl *FD, AnalysisManager &mgr, BugReporter &BR) const { if (FD->hasAttr<CMSThreadSafeAttr>() || FD->hasAttr<CMSSaAllowAttr>()) return; if (FD->isInExternCContext()) { std::string buf; std::string dname = FD->getQualifiedNameAsString(); if (dname.compare(dname.size() - 1, 1, "_") == 0) { llvm::raw_string_ostream os(buf); os << "function '" << dname << "' is in an extern \"C\" context and most likely accesses or modifies fortran variables in a " "'COMMONBLOCK'.\n"; clang::ento::PathDiagnosticLocation FDLoc = clang::ento::PathDiagnosticLocation::createBegin(FD, BR.getSourceManager()); BR.EmitBasicReport(FD, #if LLVM_VERSION_MAJOR >= 21 this->getName(), #else this->getCheckerName(), #endif "COMMONBLOCK variable accessed or modified", "ThreadSafety", os.str(), FDLoc); std::string ostring = "function '" + dname + "' static variable 'COMMONBLOCK'.\n"; std::string tname = "function-checker.txt.unsorted"; support::writeLog(ostring, tname); } } const char *sfile = BR.getSourceManager().getPresumedLoc(FD->getLocation()).getFilename(); if (!support::isCmsLocalFile(sfile)) return; std::string fname(sfile); if (!support::isInterestingLocation(fname)) return; if (FD->doesThisDeclarationHaveABody()) { FWalker walker(this, BR, mgr.getAnalysisDeclContext(FD)); walker.Visit(FD->getBody()); } } void FunctionChecker::checkASTDecl(const FunctionTemplateDecl *TD, AnalysisManager &mgr, BugReporter &BR) const { if (TD->hasAttr<CMSThreadSafeAttr>() || TD->hasAttr<CMSSaAllowAttr>()) return; const char *sfile = BR.getSourceManager().getPresumedLoc(TD->getLocation()).getFilename(); if (!support::isCmsLocalFile(sfile)) return; std::string fname(sfile); if (!support::isInterestingLocation(fname)) return; for (auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) { if (I->doesThisDeclarationHaveABody()) { FWalker walker(this, BR, mgr.getAnalysisDeclContext(*I)); walker.Visit(I->getBody()); } } return; } } // namespace clangcms