Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:51

0001 #include "ThrUnsafeFCallChecker.h"
0002 #include <iostream>
0003 #include <fstream>
0004 #include <iterator>
0005 #include <string>
0006 
0007 using namespace clang;
0008 using namespace ento;
0009 using namespace llvm;
0010 
0011 namespace clangcms {
0012 
0013   class TUFWalker : public clang::StmtVisitor<TUFWalker> {
0014     const CheckerBase *Checker;
0015     clang::ento::BugReporter &BR;
0016     clang::AnalysisDeclContext *AC;
0017 
0018   public:
0019     TUFWalker(const CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac)
0020         : Checker(checker), BR(br), AC(ac) {}
0021 
0022     void VisitChildren(clang::Stmt *S);
0023     void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
0024     void VisitCXXMemberCallExpr(clang::CXXMemberCallExpr *CE);
0025   };
0026 
0027   void TUFWalker::VisitChildren(clang::Stmt *S) {
0028     for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I)
0029       if (clang::Stmt *child = *I) {
0030         Visit(child);
0031       }
0032   }
0033 
0034   void TUFWalker::VisitCXXMemberCallExpr(CXXMemberCallExpr *CE) {
0035     CXXMethodDecl *MD = CE->getMethodDecl();
0036     if (!MD)
0037       return;
0038     const CXXMethodDecl *PD = llvm::dyn_cast_or_null<CXXMethodDecl>(AC->getDecl());
0039     if (!PD)
0040       return;
0041     std::string mname = support::getQualifiedName(*MD);
0042     std::string pname = support::getQualifiedName(*PD);
0043     llvm::SmallString<100> buf;
0044     llvm::raw_svector_ostream os(buf);
0045     const std::string tfname = "TFileService::";
0046     const std::string eoname = "edm::one";
0047     if (mname.substr(0, tfname.length()) == tfname) {
0048       for (auto I = PD->begin_overridden_methods(), E = PD->end_overridden_methods(); I != E; ++I) {
0049         std::string oname = support::getQualifiedName(*(*I));
0050         if (oname.substr(0, eoname.length()) != eoname) {
0051           os << "TFileService function " << mname << " is called in function " << pname;
0052           PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0053           BugType *BT = new BugType(Checker, "TFileService function called ", "ThreadSafety");
0054           std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, os.str(), CELoc);
0055           R->setDeclWithIssue(AC->getDecl());
0056           R->addRange(CE->getSourceRange());
0057           BR.emitReport(std::move(R));
0058           std::string tname = "function-checker.txt.unsorted";
0059           std::string ostring = "function '" + pname + "' known thread unsafe function '" + mname + "'.\n";
0060           support::writeLog(ostring, tname);
0061         }
0062       }
0063     } else if (support::isKnownThrUnsafeFunc(mname)) {
0064       os << "Known thread unsafe function " << mname << " is called in function " << pname;
0065       PathDiagnosticLocation CELoc = PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0066       BugType *BT = new BugType(Checker, "known thread unsafe function called", "ThreadSafety");
0067       std::unique_ptr<BasicBugReport> R = std::make_unique<BasicBugReport>(*BT, os.str(), CELoc);
0068       R->setDeclWithIssue(AC->getDecl());
0069       R->addRange(CE->getSourceRange());
0070       BR.emitReport(std::move(R));
0071       std::string tname = "function-checker.txt.unsorted";
0072       std::string ostring = "function '" + pname + "' known thread unsafe function '" + mname + "'.\n";
0073       support::writeLog(ostring, tname);
0074     }
0075   }
0076 
0077   void ThrUnsafeFCallChecker::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0078     const SourceManager &SM = BR.getSourceManager();
0079     PathDiagnosticLocation DLoc = PathDiagnosticLocation::createBegin(MD, SM);
0080     if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0081       return;
0082     if (!MD->doesThisDeclarationHaveABody())
0083       return;
0084     clangcms::TUFWalker walker(this, BR, mgr.getAnalysisDeclContext(MD));
0085     walker.Visit(MD->getBody());
0086     return;
0087   }
0088 
0089   void ThrUnsafeFCallChecker::checkASTDecl(const FunctionTemplateDecl *TD,
0090                                            AnalysisManager &mgr,
0091                                            BugReporter &BR) const {
0092     const clang::SourceManager &SM = BR.getSourceManager();
0093     clang::ento::PathDiagnosticLocation DLoc = clang::ento::PathDiagnosticLocation::createBegin(TD, SM);
0094     if (SM.isInSystemHeader(DLoc.asLocation()) || SM.isInExternCSystemHeader(DLoc.asLocation()))
0095       return;
0096 
0097     for (auto I = TD->spec_begin(), E = TD->spec_end(); I != E; ++I) {
0098       if (I->doesThisDeclarationHaveABody()) {
0099         clangcms::TUFWalker walker(this, BR, mgr.getAnalysisDeclContext(*I));
0100         walker.Visit(I->getBody());
0101       }
0102     }
0103     return;
0104   }
0105 
0106 }  // namespace clangcms