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