void ConstCastAwayChecker::checkPreStmt(const clang::ExplicitCastExpr* CE, clang::ento::CheckerContext& C) const { const clang::Expr* E = CE->getSubExpr(); clang::ASTContext& Ctx = C.getASTContext(); clang::QualType OrigTy = Ctx.getCanonicalType(E->getType()); clang::QualType ToTy = Ctx.getCanonicalType(CE->getType()); if (support::isConst(OrigTy) && !support::isConst(ToTy)) { clang::ento::ExplodedNode* errorNode = C.addTransition(); if (errorNode) { const char* msg = "[sas.ThreadSafety.ConstCastAwayChecker]const qualifier was removed via a cast, this may result in thread-unsafe code."; Report(CE, msg, C); } } }
bool CmsException::reportConstCast( const clang::ento::BugReport &R, clang::ento::CheckerContext &C) const { clang::ento::BugReporter &BR = C.getBugReporter(); const clang::SourceManager &SM = BR.getSourceManager(); clang::ento::PathDiagnosticLocation const& path = R.getLocation(SM); return reportGeneral ( path, BR ); }
void ConstCastAwayChecker::checkPreStmt(const clang::ExplicitCastExpr *CE, clang::ento::CheckerContext &C) const { if (! ( clang::CStyleCastExpr::classof(CE) || clang::CXXConstCastExpr::classof(CE) )) return; const Expr * SE = CE->getSubExpr(); const CXXRecordDecl * CRD = nullptr; std::string cname; if (SE->getType()->isPointerType()) CRD = SE->getType()->getPointeeCXXRecordDecl(); else CRD = SE->getType()->getAsCXXRecordDecl(); if (CRD) cname = CRD->getQualifiedNameAsString(); clang::ASTContext &Ctx = C.getASTContext(); clang::QualType OrigTy = Ctx.getCanonicalType(SE->getType()); clang::QualType ToTy = Ctx.getCanonicalType(CE->getType()); if ( support::isConst( OrigTy ) && ! support::isConst(ToTy) ) { if ( clang::ento::ExplodedNode *errorNode = C.generateErrorNode()) { if (!BT) BT.reset(new clang::ento::BugType(this,"const cast away","ConstThreadSafety")); std::string buf; llvm::raw_string_ostream os(buf); os << "const qualifier was removed via a cast, this may result in thread-unsafe code."; std::unique_ptr<clang::ento::BugReport> R = llvm::make_unique<clang::ento::BugReport>(*BT, os.str(), errorNode); R->addRange(CE->getSourceRange()); if ( ! m_exception.reportConstCastAway( *R, C ) ) return; C.emitReport(std::move(R)); if (cname == "") return; std::string tname ="constcastaway-checker.txt.unsorted"; std::string tolog ="flagged class '"+cname+"' const qualifier cast away"; support::writeLog(tolog,tname); } } }
void ConstCastChecker::checkPreStmt(const clang::CXXConstCastExpr *CE, clang::ento::CheckerContext &C) const { const Expr * SE = CE->getSubExprAsWritten(); const CXXRecordDecl * CRD = 0; if (SE->getType()->isPointerType()) CRD = SE->getType()->getPointeeCXXRecordDecl(); else CRD = SE->getType()->getAsCXXRecordDecl(); if (CRD) { std::string cname = CRD->getQualifiedNameAsString(); if (! support::isDataClass(cname) ) return; } if (clang::ento::ExplodedNode *errorNode = C.generateSink()) { if (!BT) BT.reset(new clang::ento::BugType(this,"const_cast used on a pointer to a data class ", "ThreadSafety")); clang::ento::BugReport *R = new clang::ento::BugReport(*BT, "const_cast was used on a pointer to a data class ", errorNode); R->addRange(CE->getSourceRange()); if ( ! m_exception.reportConstCast( *R, C ) ) return; C.emitReport(R); } }
void ConstCastAwayChecker::checkPreStmt(const clang::ExplicitCastExpr *CE, clang::ento::CheckerContext &C) const { const clang::Expr *E = CE->getSubExpr(); clang::ASTContext &Ctx = C.getASTContext(); clang::QualType OrigTy = Ctx.getCanonicalType(E->getType()); clang::QualType ToTy = Ctx.getCanonicalType(CE->getType()); if ( support::isConst( OrigTy ) && ! support::isConst(ToTy) ) { if ( clang::ento::ExplodedNode *errorNode = C.generateSink()) { if (!BT) BT.reset( new clang::ento::BugType("const cast away", "ThreadSafety")); clang::ento::BugReport *R = new clang::ento::BugReport(*BT, "const qualifier was removed via a cast, this may result in thread-unsafe code.", errorNode); R->addRange(CE->getSourceRange()); if ( ! m_exception.reportConstCastAway( *R, C ) ) return; C.emitReport(R); } } }
void TypeConfusionChecker::checkPreStmt(const clang::CastExpr *CE, clang::ento::CheckerContext &C) const { if (isa<ImplicitCastExpr>(CE)) return; DEBUG_PRINT("Explicit cast expression"); // CE->dump(); const auto *E = CE->getSubExpr()->IgnoreParenImpCasts(); if (!isa<DeclRefExpr>(E)) return; DEBUG_PRINT("Found declref expr"); ProgramStateRef State = C.getState(); const ValueDecl *VD = cast<DeclRefExpr>(E)->getDecl(); const QualType *QT = State->get<TypeMap>(VD); if (!QT) return; DEBUG_PRINT("Obtained value from key"); // Compare Cast To type to T if (!isa<ExplicitCastExpr>(CE)) return; const Type *castTo = cast<ExplicitCastExpr>(CE)->getTypeAsWritten().getTypePtr(); std::string declName, Message, castFromTyString, castToTyString; castToTyString = castTo->getCanonicalTypeInternal().getAsString(); castFromTyString = QT->getAsString(); if (castToTyString.compare(castFromTyString) == 0) return; DEBUG_PRINT("Type comparison failed"); if (isa<NamedDecl>(VD)) declName = cast<NamedDecl>(VD)->getQualifiedNameAsString(); Message = declName + " is unsafely cast from " + castFromTyString + " to " + castToTyString; reportBug(C, CE->getSourceRange(), Message, declName); }
void PtrCastWinChecker::checkPreStmt(const clang::CStyleCastExpr* CE, clang::ento::CheckerContext& C) const { if (clang::CK_PointerToIntegral != CE->getCastKind()) return; auto subExpr = CE->getSubExpr(); auto& Ctx = C.getASTContext(); clang::QualType fromQType = Ctx.getCanonicalType(subExpr->getType()); clang::QualType toQType = Ctx.getCanonicalType(CE->getType()); if (fromQType->isPointerType() || fromQType->isArrayType()) { auto toType = toQType.getTypePtr(); // Case one: the toType is a builtin and not a long long if (toType->isSpecificBuiltinType(clang::BuiltinType::Long) || toType->isSpecificBuiltinType(clang::BuiltinType::ULong)){ std::string r = "[sas.CodingConventions.ROOT.PtrCastWinChecker] Casting pointers to integer types which are not (unsigned) long long (in this case a "; r+=toQType.getAsString (); r+=") is wrong on Windows 64 bits. "; Report(CE, r.c_str(), C); } } }
void getParamDumper::analyzerEval(const clang::CallExpr *CE, clang::ento::CheckerContext &C) const { if ( ! C.getSourceManager().isInMainFile(CE->getExprLoc()) ) return; const FunctionDecl * FD = CE->getDirectCallee(); if (!FD) return; std::string mname = support::getQualifiedName(*FD); const char *sfile=C.getSourceManager().getPresumedLoc(CE->getExprLoc()).getFilename(); std::string sname(sfile); if ( ! support::isInterestingLocation(sname) ) return; std::string mdname; const FunctionDecl * MD = C.getCurrentAnalysisDeclContext()->getDecl()->getAsFunction(); if (!MD) return; mdname = MD->getQualifiedNameAsString(); for ( unsigned I=0, E=MD->getNumParams(); I != E; ++I) { std::string ps = "const class edm::ParameterSet "; std::string ups = "const class edm::UntrackedParameterSet "; std::string pname = MD->getParamDecl(I)->getQualifiedNameAsString(); std::string qname = MD->getParamDecl(I)->getType().getCanonicalType().getAsString(); // if (qname.substr(0,ps.length()) == ps || qname.substr(0,ups.length()) == ups) { std::string buf; llvm::raw_string_ostream os(buf); os << "in function decl '"<< mdname << "' with parameter '"<< qname << " " << pname <<"'\n"; // } } const CXXMemberCallExpr * CXE = llvm::dyn_cast_or_null<CXXMemberCallExpr>(CE); if (!CXE) return; const Expr * IOA = CXE->getImplicitObjectArgument(); std::string tname = "getparam-dumper.txt.unsorted"; std::string gp = "edm::ParameterSet::getParameter"; std::string gup = "edm::ParameterSet::getUntrackedParameter"; if (mname.substr(0,gp.length()) == gp || mname.substr(0,gup.length()) == gup ) { std::string buf; llvm::raw_string_ostream os(buf); os << "in function decl '" << mdname << "' member function call '"; clang::LangOptions LangOpts; LangOpts.CPlusPlus = true; clang::PrintingPolicy Policy(LangOpts); os << support::getQualifiedName(*(CXE->getMethodDecl())); os << "' with args '"; for ( unsigned I=0, E=CE->getNumArgs(); I != E; ++I) { if (I) os <<", "; CE->getArg(I)->printPretty(os,0,Policy); } os << "' with implicit object '"; const Expr * E = IOA->IgnoreParenNoopCasts(C.getASTContext()); QualType QE = E->getType().getCanonicalType(); os << QE.getAsString()<<" "; switch( E->getStmtClass() ) { case Stmt::MemberExprClass: os << dyn_cast<MemberExpr>(E)->getMemberDecl()->getQualifiedNameAsString(); break; case Stmt::DeclRefExprClass: os << dyn_cast<DeclRefExpr>(E)->getDecl()->getQualifiedNameAsString(); break; case Stmt::CXXOperatorCallExprClass: dyn_cast<CXXOperatorCallExpr>(E)->printPretty(os,0,Policy); break; case Stmt::CXXBindTemporaryExprClass: dyn_cast<CXXBindTemporaryExpr>(E)->printPretty(os,0,Policy); break; case Stmt::CXXMemberCallExprClass: dyn_cast<CXXMemberCallExpr>(E)->printPretty(os,0,Policy); break; case Stmt::UnaryOperatorClass: dyn_cast<UnaryOperator>(E)->printPretty(os,0,Policy); break; default: E->printPretty(os,0,Policy); os << " unhandled expr class " <<E->getStmtClassName(); } os<<"'\n"; support::writeLog(os.str(),tname); } return ; }