1+ /* *
2+ * @file FutagSimpleChecker.cpp
3+ * @author Tran Chi Thien (thientcgithub@gmail.com)
4+ * @brief
5+ * @version 2.0.5
6+ * @date 2023-04-17
7+ *
8+ * @copyright Copyright (c) 2023
9+ *
10+ */
11+
12+ #include < algorithm>
13+ #include < fstream>
14+ #include < iomanip>
15+ #include < iostream>
16+ #include < sstream>
17+ #include < string>
18+ #include < thread>
19+ #include < utility>
20+ #include < vector>
21+
22+ #include " Futag/MatchFinder.h"
23+ #include " nlohmann/json.hpp"
24+ #include " clang/AST/Decl.h"
25+ #include " clang/AST/ODRHash.h"
26+ #include " clang/AST/RecursiveASTVisitor.h"
27+ #include " clang/AST/Type.h"
28+ #include " clang/ASTMatchers/ASTMatchFinder.h"
29+ #include " clang/ASTMatchers/ASTMatchers.h"
30+ #include " clang/Analysis/AnalysisDeclContext.h"
31+ #include " clang/Analysis/CFG.h"
32+ #include " clang/Basic/SourceManager.h"
33+ #include " clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
34+ #include " clang/StaticAnalyzer/Core/BugReporter/BugType.h"
35+ #include " clang/StaticAnalyzer/Core/Checker.h"
36+ #include " clang/StaticAnalyzer/Core/CheckerManager.h"
37+ #include " clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
38+ #include " clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
39+ #include " clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
40+ #include " clang/Tooling/Tooling.h"
41+ #include " llvm/ADT/SmallVector.h"
42+ #include " llvm/ADT/StringRef.h"
43+ #include " llvm/Support/ErrorHandling.h"
44+ #include " llvm/Support/FileSystem.h"
45+ #include " llvm/Support/Path.h"
46+
47+ #include " llvm/Support/raw_ostream.h"
48+
49+ #include " Futag/Basic.h"
50+ #include " Futag/Utils.h"
51+
52+ using namespace llvm ;
53+ using namespace clang ;
54+ using namespace ento ;
55+ using namespace nlohmann ;
56+ using namespace futag ;
57+
58+ // ===----------------------------------------------------------------------===//
59+ // Checker to analyze function declarations
60+ // ===----------------------------------------------------------------------===//
61+ namespace {
62+
63+ class FutagMatchFuncDeclCallBack : public MatchFinder ::MatchCallback {
64+ public:
65+ FutagMatchFuncDeclCallBack ( AnalysisManager &Mgr)
66+ : Mgr{Mgr} {}
67+ AnalysisManager &Mgr; // For passing the AnalysisManager
68+ virtual void run (const MatchFinder::MatchResult &Result);
69+ };
70+
71+ class FutagSimpleChecker : public Checker <check::ASTDecl<TranslationUnitDecl>> {
72+
73+ public:
74+ // Entry point. Collects all needed information using recursive ast visitor
75+ void checkASTDecl (const TranslationUnitDecl *TUD, AnalysisManager &Mgr,
76+ BugReporter &BR) const ;
77+
78+ /* Collects information about function */
79+ void VisitFunction (const FunctionDecl *func, AnalysisManager &Mgr) const ;
80+ /* Collects information about struct declarations*/
81+ void VisitRecord (const RecordDecl *func, AnalysisManager &Mgr) const ;
82+ /* Collects information about typedefs */
83+ void VisitTypedef (const TypedefDecl *func, AnalysisManager &Mgr) const ;
84+ /* Collects information about enums */
85+ void VisitEnum (const EnumDecl *func, AnalysisManager &Mgr) const ;
86+ };
87+
88+ } // namespace
89+
90+ void FutagMatchFuncDeclCallBack::run (const MatchFinder::MatchResult &Result) {
91+ const auto *func_decl = Result.Nodes .getNodeAs <FunctionDecl>(" functionDe" );
92+
93+ if (!func_decl) {
94+ return ;
95+ }
96+ llvm::outs ()<< " \n -- Found function declaration: \" " << func_decl->getDeclName ().getAsString () << " " ;
97+ // If the available function is defined in system header file, then skip.
98+
99+ FullSourceLoc func_begin_loc =
100+ Mgr.getASTContext ().getFullLoc (func_decl->getBeginLoc ());
101+ int32_t curr_func_begin_loc = func_begin_loc.getSpellingLineNumber ();
102+ auto fe = func_begin_loc.getFileEntry ();
103+ std::string file_name;
104+ std::string parent_hash = " " ;
105+
106+ if (fe->tryGetRealPathName ().empty ()) {
107+ if (fe->getName ().empty ()) {
108+ std::cerr << " -- Debug info: Cannot find filename and filepath!\n " ;
109+ } else {
110+ file_name = fe->getName ().str ();
111+ }
112+ } else {
113+ file_name = fe->tryGetRealPathName ().str ();
114+ }
115+ llvm::outs ()<< " in file \" " << file_name << " \" \n\n " ;
116+ return ;
117+ }
118+ void FutagSimpleChecker::checkASTDecl (const TranslationUnitDecl *TUD,
119+ AnalysisManager &Mgr, BugReporter &BR) const {
120+
121+ struct LocalVisitor : public RecursiveASTVisitor <LocalVisitor> {
122+ const FutagSimpleChecker *futag_checker;
123+ AnalysisManager &analysisMgr;
124+
125+ explicit LocalVisitor (const FutagSimpleChecker *Checker,
126+ AnalysisManager &AnalysisMgr)
127+ : futag_checker(Checker), analysisMgr(AnalysisMgr) {}
128+
129+ /* callback when a function declaration is encountered */
130+ bool VisitFunctionDecl (FunctionDecl *FD) {
131+ futag_checker->VisitFunction (FD, analysisMgr);
132+ return true ;
133+ }
134+
135+ /* callback when a struct declaration is encountered */
136+ bool VisitRecordDecl (RecordDecl *RD) {
137+ futag_checker->VisitRecord (RD, analysisMgr);
138+ return true ;
139+ }
140+
141+ /* callback when a typedef declaration is encountered */
142+ bool VisitTypedefDecl (TypedefDecl *TD) {
143+ futag_checker->VisitTypedef (TD, analysisMgr);
144+ return true ;
145+ }
146+
147+ /* callback when a enum declaration is encountered */
148+ bool VisitEnumDecl (EnumDecl *ED) {
149+ futag_checker->VisitEnum (ED, analysisMgr);
150+ return true ;
151+ }
152+ };
153+
154+ LocalVisitor visitor (this , Mgr);
155+ visitor.TraverseDecl (const_cast <TranslationUnitDecl *>(TUD));
156+ }
157+
158+ // Called for every function declaration
159+ void FutagSimpleChecker::VisitFunction (const FunctionDecl *func,
160+ AnalysisManager &Mgr) const {
161+ llvm::outs ()<< " -- Analyzing function: \" " << func->getDeclName ().getAsString () << " \"\n " ;
162+ // If the available function is defined in system header file, then skip.
163+ if (Mgr.getSourceManager ().isInSystemHeader (func->getBeginLoc ())) {
164+ llvm::outs ()<< " } \" " << func->getDeclName ().getAsString () << " \" is in system headers!\n " ;
165+ return ;
166+ }
167+
168+
169+ FullSourceLoc func_begin_loc =
170+ Mgr.getASTContext ().getFullLoc (func->getBeginLoc ());
171+ FullSourceLoc func_end_loc =
172+ Mgr.getASTContext ().getFullLoc (func->getEndLoc ());
173+ if (!func_begin_loc.getFileEntry ()) {
174+ return ;
175+ }
176+ int32_t curr_func_begin_loc = func_begin_loc.getSpellingLineNumber ();
177+ auto fe = func_begin_loc.getFileEntry ();
178+ std::string file_name;
179+ std::string parent_hash = " " ;
180+
181+ if (fe->tryGetRealPathName ().empty ()) {
182+ if (fe->getName ().empty ()) {
183+ std::cerr << " -- Debug info: Cannot find filename and filepath!\n " ;
184+ } else {
185+ file_name = fe->getName ().str ();
186+ }
187+ } else {
188+ file_name = fe->tryGetRealPathName ().str ();
189+ }
190+ llvm::outs ()<< " in file \" " << file_name << " \" \n " ;
191+
192+ MatchFinder Finder;
193+ // Match all CallExpression of target function
194+ auto match_callexpr =
195+ functionDecl (hasName (func->getDeclName ().getAsString ()))
196+ .bind (" functionDe" );
197+
198+ FutagMatchFuncDeclCallBack target_func_call_callback{ Mgr};;
199+ Finder.addMatcher (match_callexpr, &target_func_call_callback);
200+ Finder.matchAST (Mgr.getASTContext ());
201+
202+ return ;
203+ }
204+
205+ void FutagSimpleChecker::VisitRecord (const RecordDecl *RD,
206+ AnalysisManager &Mgr) const {
207+
208+ return ;
209+ }
210+ void FutagSimpleChecker::VisitTypedef (const TypedefDecl *TD,
211+ AnalysisManager &Mgr) const {
212+ return ;
213+ }
214+
215+ void FutagSimpleChecker::VisitEnum (const EnumDecl *ED, AnalysisManager &Mgr) const {
216+ return ;
217+ }
218+
219+ void ento::registerFutagSimpleChecker (CheckerManager &Mgr) {
220+ Mgr.registerChecker <FutagSimpleChecker>();
221+ }
222+
223+ bool ento::shouldRegisterFutagSimpleChecker (const CheckerManager &mgr) {
224+ return true ;
225+ }
0 commit comments