Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "ArgSizeChecker.h"
0002 #include <clang/AST/AST.h>
0003 #include <clang/AST/ASTConsumer.h>
0004 #include <clang/AST/DeclGroup.h>
0005 #include <clang/AST/RecursiveASTVisitor.h>
0006 #include <clang/AST/Expr.h>
0007 #include <clang/AST/CharUnits.h>
0008 #include <llvm/ADT/SmallString.h>
0009 #include <clang/StaticAnalyzer/Core/BugReporter/BugReporter.h>
0010 #include <clang/StaticAnalyzer/Core/BugReporter/BugType.h>
0011 #include <clang/AST/ParentMap.h>
0012 
0013 #include "CmsSupport.h"
0014 #include <iostream>
0015 using namespace clang;
0016 using namespace ento;
0017 using namespace llvm;
0018 
0019 namespace clangcms {
0020 
0021   void ArgSizeChecker::checkPreStmt(const CXXConstructExpr *E, CheckerContext &ctx) const {
0022     CmsException m_exception;
0023     clang::LangOptions LangOpts;
0024     LangOpts.CPlusPlus = true;
0025     clang::PrintingPolicy Policy(LangOpts);
0026 
0027     const clang::ento::PathDiagnosticLocation ELoc =
0028         clang::ento::PathDiagnosticLocation::createBegin(E, ctx.getSourceManager(), ctx.getLocationContext());
0029 
0030     if (!m_exception.reportGeneral(ELoc, ctx.getBugReporter()))
0031       return;
0032     llvm::SmallString<100> buf;
0033     llvm::raw_svector_ostream os(buf);
0034 
0035     for (clang::Stmt::const_child_iterator I = E->child_begin(), F = E->child_end(); I != F; ++I) {
0036       const Expr *child = llvm::dyn_cast_or_null<Expr>(*I);
0037       if (!child)
0038         continue;
0039       if (llvm::isa<DeclRefExpr>(child->IgnoreImpCasts())) {
0040         const NamedDecl *ND = llvm::cast<DeclRefExpr>(child->IgnoreImpCasts())->getFoundDecl();
0041         if (llvm::isa<ParmVarDecl>(ND)) {
0042           const ParmVarDecl *PVD = llvm::cast<ParmVarDecl>(ND);
0043           QualType QT = PVD->getOriginalType();
0044           if (QT->isIncompleteType() || QT->isDependentType())
0045             continue;
0046           clang::QualType PQT = QT.getCanonicalType();
0047           PQT.removeLocalConst();
0048           if (PQT->isReferenceType() || PQT->isPointerType() || PQT->isMemberFunctionPointerType() ||
0049               PQT->isArrayType() || PQT->isBuiltinType() || PQT->isUnionType() || PQT->isVectorType())
0050             continue;
0051           uint64_t size_param = ctx.getASTContext().getTypeSize(PQT);
0052           uint64_t max_bits = 128;
0053           if (size_param <= max_bits)
0054             continue;
0055           std::string qname = QT.getAsString();
0056           std::string pname = PQT.getAsString();
0057           const CXXMethodDecl *MD =
0058               llvm::dyn_cast_or_null<CXXMethodDecl>(ctx.getCurrentAnalysisDeclContext()->getDecl());
0059           os << "Function parameter copied by value with size '" << size_param << "' bits > max size '" << max_bits
0060              << "' bits parameter type '" << pname << "' function '";
0061 
0062           if (MD) {
0063             std::string fname = MD->getNameAsString();
0064             os << fname << "' class '" << MD->getParent()->getNameAsString();
0065           }
0066           os << "'\n";
0067 
0068           std::string oname = "operator";
0069 
0070           const clang::ento::PathDiagnosticLocation DLoc =
0071               clang::ento::PathDiagnosticLocation::createBegin(PVD, ctx.getSourceManager());
0072 
0073           BugType *BT = new BugType(this, "Function parameter copied by value with size > max", "ArgSize");
0074           std::unique_ptr<BasicBugReport> report =
0075               std::make_unique<BasicBugReport>(*BT, llvm::StringRef(os.str()), DLoc);
0076           report->addRange(PVD->getSourceRange());
0077           ctx.emitReport(std::move(report));
0078         }
0079       }
0080     }
0081   }
0082 
0083   void ArgSizeChecker::checkASTDecl(const CXXMethodDecl *MD, AnalysisManager &mgr, BugReporter &BR) const {
0084     const SourceManager &SM = BR.getSourceManager();
0085     CmsException m_exception;
0086     PathDiagnosticLocation DLoc = PathDiagnosticLocation::createBegin(MD, SM);
0087 
0088     if (!m_exception.reportGeneral(DLoc, BR))
0089       return;
0090 
0091     for (CXXMethodDecl::param_const_iterator I = MD->param_begin(), E = MD->param_end(); I != E; I++) {
0092       llvm::SmallString<100> buf;
0093       llvm::raw_svector_ostream os(buf);
0094       QualType QT = (*I)->getOriginalType();
0095       if (QT->isIncompleteType() || QT->isDependentType())
0096         continue;
0097       clang::QualType PQT = QT.getCanonicalType();
0098       PQT.removeLocalConst();
0099       if (PQT->isReferenceType() || PQT->isPointerType() || PQT->isMemberFunctionPointerType() || PQT->isArrayType() ||
0100           PQT->isBuiltinType() || PQT->isUnionType() || PQT->isVectorType())
0101         continue;
0102       uint64_t size_param = mgr.getASTContext().getTypeSize(PQT);
0103       uint64_t max_bits = 128;
0104       if (size_param <= max_bits)
0105         continue;
0106       std::string qname = QT.getAsString();
0107       std::string pname = PQT.getAsString();
0108       std::string fname = MD->getNameAsString();
0109       os << "Function parameter passed by value with size of parameter '" << size_param << "' bits > max size '"
0110          << max_bits << "' bits parameter type '" << pname << "' function '" << fname << "' class '"
0111          << MD->getParent()->getNameAsString() << "'\n";
0112       std::string oname = "operator";
0113 
0114       BugType *BT = new BugType(this, "Function parameter with size > max", "ArgSize");
0115       std::unique_ptr<BasicBugReport> report = std::make_unique<BasicBugReport>(*BT, llvm::StringRef(os.str()), DLoc);
0116       BR.emitReport(std::move(report));
0117     }
0118   }
0119 
0120 }  // namespace clangcms