File indexing completed on 2023-03-17 11:26:53
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 }