File indexing completed on 2024-04-06 12:31:51
0001 #include <clang/AST/Attr.h>
0002 #include <clang/AST/DeclCXX.h>
0003 #include <clang/AST/ExprCXX.h>
0004 #include <clang/AST/Expr.h>
0005 #include <clang/AST/Decl.h>
0006 #include <clang/AST/DeclTemplate.h>
0007 #include <clang/AST/StmtVisitor.h>
0008 #include <clang/AST/ParentMap.h>
0009 #include <clang/Analysis/CFGStmtMap.h>
0010 #include <clang/Analysis/CallGraph.h>
0011 #include <llvm/Support/SaveAndRestore.h>
0012 #include <clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h>
0013 #include <clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h>
0014 #include <clang/StaticAnalyzer/Core/Checker.h>
0015 #include <clang/StaticAnalyzer/Core/BugReporter/BugReporter.h>
0016 #include <clang/StaticAnalyzer/Core/BugReporter/BugType.h>
0017 #include <llvm/ADT/SmallString.h>
0018 #include "TrunCastChecker.h"
0019 #include "CmsSupport.h"
0020
0021 using namespace clang;
0022 using namespace ento;
0023 using namespace llvm;
0024
0025 namespace clangcms {
0026
0027 class ICEVisitor : public clang::StmtVisitor<ICEVisitor> {
0028 const clang::ento::CheckerBase *Checker;
0029 clang::ento::BugReporter &BR;
0030 clang::AnalysisDeclContext *AC;
0031
0032 public:
0033 ICEVisitor(const clang::ento::CheckerBase *checker, clang::ento::BugReporter &br, clang::AnalysisDeclContext *ac)
0034 : Checker(checker), BR(br), AC(ac) {}
0035
0036 void VisitImplicitCastExpr(ImplicitCastExpr *CE);
0037 void VisitBinaryOperator(BinaryOperator *BO);
0038 void VisitChildren(clang::Stmt *S);
0039 void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
0040 };
0041
0042 void ICEVisitor::VisitChildren(clang::Stmt *S) {
0043 for (auto I = S->child_begin(), E = S->child_end(); I != E; ++I)
0044 if (clang::Stmt *child = *I) {
0045 Visit(child);
0046 }
0047 }
0048
0049 void ICEVisitor::VisitBinaryOperator(BinaryOperator *BO) {
0050 const NamedDecl *ACD = dyn_cast_or_null<NamedDecl>(AC->getDecl());
0051 VisitChildren(BO);
0052 std::string ename = "EventNumber_t";
0053 clang::Expr *LHS = BO->getLHS();
0054 clang::Expr *RHS = BO->getRHS();
0055 if (!LHS || !RHS)
0056 return;
0057 std::string lname = LHS->getType().getAsString();
0058 std::string rname = RHS->getType().getAsString();
0059 if (IntegerLiteral::classof(LHS->IgnoreCasts()) || IntegerLiteral::classof(RHS->IgnoreCasts()))
0060 return;
0061 if (!(lname == ename || rname == ename))
0062 return;
0063 if (lname == ename && rname == ename)
0064 return;
0065 clang::QualType OTy;
0066 clang::QualType TTy;
0067 if (lname == ename && ImplicitCastExpr::classof(RHS)) {
0068 ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(RHS);
0069 TTy = BR.getContext().getCanonicalType(LHS->getType());
0070 OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType());
0071 }
0072 if (rname == ename && ImplicitCastExpr::classof(LHS)) {
0073 ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(LHS);
0074 TTy = BR.getContext().getCanonicalType(RHS->getType());
0075 OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType());
0076 }
0077 if (TTy.isNull() || OTy.isNull())
0078 return;
0079 QualType ToTy = TTy.getUnqualifiedType();
0080 QualType OrigTy = OTy.getUnqualifiedType();
0081 if (!(ToTy->isIntegerType() || ToTy->isFloatingType()))
0082 return;
0083 if (ToTy->isBooleanType())
0084 return;
0085 CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy);
0086 CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy);
0087 std::string oname = OrigTy.getAsString();
0088 std::string tname = ToTy.getAsString();
0089 if (ToTy->isFloatingType()) {
0090 llvm::SmallString<100> buf;
0091 llvm::raw_svector_ostream os(buf);
0092 os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD));
0093 clang::ento::PathDiagnosticLocation CELoc =
0094 clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC);
0095 BR.EmitBasicReport(ACD,
0096 CheckerNameRef(),
0097 "implicit cast of int type to float type",
0098 "CMS code rules",
0099 os.str(),
0100 CELoc,
0101 BO->getSourceRange());
0102 }
0103 if ((size_otype > size_ttype)) {
0104 llvm::SmallString<100> buf;
0105 llvm::raw_svector_ostream os(buf);
0106 os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. "
0107 << support::getQualifiedName(*(ACD));
0108 clang::ento::PathDiagnosticLocation CELoc =
0109 clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC);
0110 BR.EmitBasicReport(ACD,
0111 CheckerNameRef(),
0112 "implicit cast of int type to smaller int type could truncate",
0113 "CMS code rules",
0114 os.str(),
0115 CELoc,
0116 BO->getSourceRange());
0117 }
0118 if ((size_otype == size_ttype) &&
0119 (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() ||
0120 ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation())) {
0121 llvm::SmallString<100> buf;
0122 llvm::raw_svector_ostream os(buf);
0123 os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. "
0124 << support::getQualifiedName(*(ACD));
0125 clang::ento::PathDiagnosticLocation CELoc =
0126 clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC);
0127 BR.EmitBasicReport(
0128 ACD, CheckerNameRef(), "implicit cast ins sign type", "CMS code rules", os.str(), CELoc, BO->getSourceRange());
0129 }
0130 return;
0131 return;
0132 }
0133
0134 void ICEVisitor::VisitImplicitCastExpr(ImplicitCastExpr *CE) {
0135 const NamedDecl *ACD = dyn_cast<NamedDecl>(AC->getDecl());
0136 VisitChildren(CE);
0137 const Expr *SE = CE->getSubExprAsWritten();
0138 std::string sename = SE->getType().getAsString();
0139 const clang::Expr *E = CE->getSubExpr();
0140 if (!(sename == "EventNumber_t"))
0141 return;
0142 QualType OTy = BR.getContext().getCanonicalType(E->getType());
0143 QualType TTy = BR.getContext().getCanonicalType(CE->getType());
0144 QualType ToTy = TTy.getUnqualifiedType();
0145 QualType OrigTy = OTy.getUnqualifiedType();
0146 if (!(ToTy->isIntegerType() || ToTy->isFloatingType()))
0147 return;
0148 if (ToTy->isBooleanType())
0149 return;
0150 CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy);
0151 CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy);
0152 std::string oname = OrigTy.getAsString();
0153 std::string tname = ToTy.getAsString();
0154 if (ToTy->isFloatingType()) {
0155 llvm::SmallString<100> buf;
0156 llvm::raw_svector_ostream os(buf);
0157 os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD));
0158 clang::ento::PathDiagnosticLocation CELoc =
0159 clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0160 BR.EmitBasicReport(ACD,
0161 CheckerNameRef(),
0162 "implicit cast of int type to float type",
0163 "CMS code rules",
0164 os.str(),
0165 CELoc,
0166 CE->getSourceRange());
0167 }
0168 if ((size_otype > size_ttype)) {
0169 llvm::SmallString<100> buf;
0170 llvm::raw_svector_ostream os(buf);
0171 os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. "
0172 << support::getQualifiedName(*(ACD));
0173 clang::ento::PathDiagnosticLocation CELoc =
0174 clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0175 BR.EmitBasicReport(ACD,
0176 CheckerNameRef(),
0177 "implicit cast of int type to smaller int type could truncate",
0178 "CMS code rules",
0179 os.str(),
0180 CELoc,
0181 CE->getSourceRange());
0182 }
0183 if (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() ||
0184 ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation()) {
0185 llvm::SmallString<100> buf;
0186 llvm::raw_svector_ostream os(buf);
0187 os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. "
0188 << support::getQualifiedName(*(ACD));
0189 clang::ento::PathDiagnosticLocation CELoc =
0190 clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
0191 BR.EmitBasicReport(ACD,
0192 CheckerNameRef(),
0193 "implicit cast changes int sign type",
0194 "CMS code rules",
0195 os.str(),
0196 CELoc,
0197 CE->getSourceRange());
0198 }
0199 return;
0200 }
0201
0202 void TrunCastChecker::checkASTDecl(const CXXRecordDecl *D, AnalysisManager &Mgr, BugReporter &BR) const {
0203 for (auto I = D->method_begin(), E = D->method_end(); I != E; ++I) {
0204 if (!llvm::isa<clang::CXXMethodDecl>((*I)))
0205 continue;
0206 clang::CXXMethodDecl *MD = llvm::cast<clang::CXXMethodDecl>((*I)->getMostRecentDecl());
0207 if (!MD->hasBody())
0208 continue;
0209 clang::Stmt *Body = MD->getBody();
0210 ICEVisitor icevisitor(this, BR, Mgr.getAnalysisDeclContext(MD));
0211 icevisitor.Visit(Body);
0212 }
0213 }
0214
0215 }