From 9179cf01080113edf74189cc6620dd8d20e5931c Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Tue, 17 Oct 2023 18:00:07 +0200 Subject: [PATCH 01/27] Analysis Printer (#17) * Initial Commit * AnalysisPrinter Second commit * Initial Commit * Integrate Printer with client Analysis and test * Addressing Review comments * Integrate AnalysisPrinter with all analyses and template class modified * vector emplace_back instead of push_back * Testcase for AnalysisPrinter * GroundTruth derived class initial commit * AnalysisPrinter Test complete and Test * fixing myphasartool file * Test pre-commit fix * Adding Test cases and fixing PR failure * 1.template params to N,D,L 2.remove AnalysisType param from AnalysisResults 3.rearranging class variables * 1.template params to N,D,L 2.remove AnalysisType param from AnalysisResults 3.rearranging class variables * Null AnalysisPrinter singleton * Adding AnalysisPrinter to IDETabulation Problem * making free (N,D,L)ToString functions * disable copy and move for analysis-printer * Default NullAnalysisPrinter and explicit print methods * removing SetAnalysisPrinter from client analyses and modified Testcase for AnalysisPrinter * Adding superclass for AnalysisPrinter * Addressing review comments and fixing PR build failure * fix: minors * fix: minor (clang-tidy) * fix: review feedback * misc: minor refactoring --------- Co-authored-by: SanthoshMohan Co-authored-by: Sriteja Kummita --- .../DataFlow/IfdsIde/IDETabulationProblem.h | 14 +- .../Utils/ExtendedValue.h | 2 + .../IfdsIde/Problems/IDETypeStateAnalysis.h | 51 ++----- .../PhasarLLVM/Utils/AnalysisPrinterBase.h | 44 ++++++ .../PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 47 +++++++ .../PhasarLLVM/Utils/NullAnalysisPrinter.h | 25 ++++ .../Problems/IDEExtendedTaintAnalysis.cpp | 12 +- .../Problems/IDEInstInteractionAnalysis.cpp | 2 + .../Problems/IFDSFieldSensTaintAnalysis.cpp | 3 +- .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 33 ++--- .../OpenSSLSecureMemoryDescription.cpp | 3 +- unittests/Utils/AnalysisPrinterTest.cpp | 128 ++++++++++++++++++ unittests/Utils/CMakeLists.txt | 1 + 13 files changed, 295 insertions(+), 70 deletions(-) create mode 100644 include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h create mode 100644 include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h create mode 100644 include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h create mode 100644 unittests/Utils/AnalysisPrinterTest.cpp diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index ab20dc3f6e..35bd80ae56 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -19,6 +19,7 @@ #include "phasar/DataFlow/IfdsIde/IFDSIDESolverConfig.h" #include "phasar/DataFlow/IfdsIde/InitialSeeds.h" #include "phasar/DataFlow/IfdsIde/SolverResults.h" +#include "phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h" #include "phasar/Utils/JoinLattice.h" #include "phasar/Utils/Printer.h" #include "phasar/Utils/Soundness.h" @@ -78,10 +79,19 @@ class IDETabulationProblem : public FlowFunctions, std::optional ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IRDB(IRDB), EntryPoints(std::move(EntryPoints)), - ZeroValue(std::move(ZeroValue)) { + ZeroValue(std::move(ZeroValue)), + Printer(NullAnalysisPrinter::getInstance()) { assert(IRDB != nullptr); } + void setAnalysisPrinter(AnalysisPrinterBase *P) { + if (P) { + Printer = P; + } else { + Printer = NullAnalysisPrinter::getInstance(); + } + } + ~IDETabulationProblem() override = default; /// Checks if the given data-flow fact is the special tautological lambda (or @@ -167,6 +177,8 @@ class IDETabulationProblem : public FlowFunctions, IFDSIDESolverConfig SolverConfig{}; [[maybe_unused]] Soundness SF = Soundness::Soundy; + + AnalysisPrinterBase *Printer; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/ExtendedValue.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/ExtendedValue.h index 10253527cc..01ff032464 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/ExtendedValue.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/ExtendedValue.h @@ -5,6 +5,8 @@ #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IFDSFIELDSENSTAINTANALYSIS_UTILS_EXTENDEDVALUE_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IFDSFIELDSENSTAINTANALYSIS_UTILS_EXTENDEDVALUE_H +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" + #include #include #include diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index 9335838f9c..866c21774c 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -519,38 +519,21 @@ class IDETypeStateAnalysis void emitTextReport(const SolverResults &SR, llvm::raw_ostream &OS = llvm::outs()) override { LLVMBasedCFG CFG; - OS << "\n======= TYPE STATE RESULTS =======\n"; for (const auto &F : this->IRDB->getAllFunctions()) { - OS << '\n' << F->getName() << '\n'; for (const auto &BB : *F) { for (const auto &I : BB) { auto Results = SR.resultsAt(&I, true); + if (CFG.isExitInst(&I)) { - OS << "\nAt exit stmt: " << NToString(&I) << '\n'; for (auto Res : Results) { if (const auto *Alloca = llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { - OS << "\n=== ERROR STATE DETECTED ===\nAlloca: " - << DToString(Res.first) << '\n'; - for (const auto *Pred : CFG.getPredsOf(&I)) { - OS << "\nPredecessor: " << NToString(Pred) << '\n'; - auto PredResults = SR.resultsAt(Pred, true); - for (auto Res : PredResults) { - if (Res.first == Alloca) { - OS << "Pred State: " << LToString(Res.second) << '\n'; - } - } - } - OS << "============================\n"; - } else { - OS << "\nAlloca : " << DToString(Res.first) - << "\nState : " << LToString(Res.second) << '\n'; + Warning> + War(&I, Res.first, TSD->error()); + // ERROR STATE DETECTED + this->Printer->onResult(War); } - } else { - OS << "\nInst: " << NToString(&I) << '\n' - << "Fact: " << DToString(Res.first) << '\n' - << "State: " << LToString(Res.second) << '\n'; } } } else { @@ -558,31 +541,19 @@ class IDETypeStateAnalysis if (const auto *Alloca = llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { - OS << "\n=== ERROR STATE DETECTED ===\nAlloca: " - << DToString(Res.first) << '\n' - << "\nAt IR Inst: " << NToString(&I) << '\n'; - for (const auto *Pred : CFG.getPredsOf(&I)) { - OS << "\nPredecessor: " << NToString(Pred) << '\n'; - auto PredResults = SR.resultsAt(Pred, true); - for (auto Res : PredResults) { - if (Res.first == Alloca) { - OS << "Pred State: " << LToString(Res.second) << '\n'; - } - } - } - OS << "============================\n"; + Warning> + War(&I, Res.first, TSD->error()); + // ERROR STATE DETECTED + this->Printer->onResult(War); } - } else { - OS << "\nInst: " << NToString(&I) << '\n' - << "Fact: " << DToString(Res.first) << '\n' - << "State: " << LToString(Res.second) << '\n'; } } } } } - OS << "\n--------------------------------------------\n"; } + + this->Printer->onFinalize(OS); } private: diff --git a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h new file mode 100644 index 0000000000..2e636396f8 --- /dev/null +++ b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h @@ -0,0 +1,44 @@ +#ifndef PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H +#define PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H + +#include "llvm/Support/raw_ostream.h" + +namespace psr { + +template struct Warning { + using n_t = typename AnalysisDomainTy::n_t; + using d_t = typename AnalysisDomainTy::d_t; + using l_t = typename AnalysisDomainTy::l_t; + + n_t Instr; + d_t Fact; + l_t LatticeElement; + + // Constructor + Warning(n_t Inst, d_t DfFact, l_t Lattice) + : Instr(std::move(Inst)), Fact(std::move(DfFact)), + LatticeElement(std::move(Lattice)) {} +}; + +template struct Results { + std::vector> War; +}; + +template class AnalysisPrinterBase { +public: + virtual void onResult(Warning /*War*/) = 0; + virtual void onInitialize() = 0; + virtual void onFinalize(llvm::raw_ostream & /*OS*/) const = 0; + + AnalysisPrinterBase() = default; + virtual ~AnalysisPrinterBase() = default; + AnalysisPrinterBase(const AnalysisPrinterBase &) = delete; + AnalysisPrinterBase &operator=(const AnalysisPrinterBase &) = delete; + + AnalysisPrinterBase(AnalysisPrinterBase &&) = delete; + AnalysisPrinterBase &operator=(AnalysisPrinterBase &&) = delete; +}; + +} // namespace psr + +#endif diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h new file mode 100644 index 0000000000..a75f912eeb --- /dev/null +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -0,0 +1,47 @@ +#ifndef PHASAR_PHASARLLVM_UTILS_DEFAULTANALYSISPRINTER_H +#define PHASAR_PHASARLLVM_UTILS_DEFAULTANALYSISPRINTER_H + +#include "phasar/Domain/BinaryDomain.h" +#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/Printer.h" + +#include +#include +#include + +namespace psr { + +template +class DefaultAnalysisPrinter : public AnalysisPrinterBase { + using l_t = typename AnalysisDomainTy::l_t; + +public: + ~DefaultAnalysisPrinter() override = default; + DefaultAnalysisPrinter() = default; + + void onResult(Warning War) override { + AnalysisResults.War.emplace_back(std::move(War)); + } + + void onInitialize() override{}; + void onFinalize(llvm::raw_ostream &OS = llvm::outs()) const override { + for (const auto &Iter : AnalysisResults.War) { + + OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; + + OS << "\tFact: " << DToString(Iter.Fact) << "\n"; + + if constexpr (std::is_same_v) { + OS << "Value: " << LToString(Iter.LatticeElement) << "\n"; + } + } + } + +private: + Results AnalysisResults{}; +}; + +} // namespace psr + +#endif diff --git a/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h new file mode 100644 index 0000000000..9007677557 --- /dev/null +++ b/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h @@ -0,0 +1,25 @@ +#ifndef PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H +#define PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H + +#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" + +namespace psr { + +template +class NullAnalysisPrinter final : public AnalysisPrinterBase { +public: + static NullAnalysisPrinter *getInstance() { + static auto Instance = NullAnalysisPrinter(); + return &Instance; + } + + void onInitialize() override{}; + void onResult(Warning /*War*/) override{}; + void onFinalize(llvm::raw_ostream & /*OS*/) const override{}; + +private: + NullAnalysisPrinter() = default; +}; + +} // namespace psr +#endif diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index 02c08a3099..e6b3cc32ab 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -227,6 +227,9 @@ void IDEExtendedTaintAnalysis::reportLeakIfNecessary( const llvm::Value *LeakCandidate) { if (isSink(SinkCandidate, Inst)) { Leaks[Inst].insert(LeakCandidate); + Warning War( + Inst, makeFlowFact(LeakCandidate), Top{}); + Printer->onResult(War); } } @@ -744,19 +747,20 @@ auto IDEExtendedTaintAnalysis::getSummaryEdgeFunction(n_t Curr, d_t CurrNode, void IDEExtendedTaintAnalysis::emitTextReport( const SolverResults &SR, llvm::raw_ostream &OS) { - OS << "===== IDEExtendedTaintAnalysis-Results =====\n"; if (!PostProcessed) { doPostProcessing(SR); } for (auto &[Inst, LeakSet] : Leaks) { - OS << "At " << NToString(Inst) << '\n'; for (const auto &Leak : LeakSet) { - OS << "\t" << llvmIRToShortString(Leak) << "\n"; + Warning War(Inst, makeFlowFact(Leak), + Top{}); + Printer->onResult(War); } } - OS << '\n'; + + Printer->onFinalize(OS); } // Helpers: diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.cpp index 2877e3086b..d65e8ea9cf 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.cpp @@ -9,6 +9,8 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" + #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Value.h" diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp index 8b1eb73414..53d6099e7b 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp @@ -28,14 +28,13 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/DataFlowUtils.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/Support/raw_ostream.h" #include #include #include #include -#include - namespace psr { IFDSFieldSensTaintAnalysis::IFDSFieldSensTaintAnalysis( diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index c7b2b6f72e..18ff4434c3 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -16,6 +16,7 @@ #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h" +#include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/PhasarLLVM/TaintConfig/TaintConfigUtilities.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" @@ -408,7 +409,11 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, return lambdaFlow([Leak{std::move(Leak)}, Kill{std::move(Kill)}, this, CallSite](d_t Source) -> container_type { if (Leak.count(Source)) { - Leaks[CallSite].insert(Source); + if (Leaks[CallSite].insert(Source).second) { + Warning War(CallSite, Source, + topElement()); + Printer->onResult(War); + } } if (Kill.count(Source)) { @@ -433,7 +438,11 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, } if (Leak.count(Source)) { - Leaks[CallSite].insert(Source); + if (Leaks[CallSite].insert(Source).second) { + Warning War(CallSite, Source, + topElement()); + Printer->onResult(War); + } } return {Source}; @@ -478,25 +487,7 @@ void IFDSTaintAnalysis::emitTextReport( const SolverResults & /*SR*/, llvm::raw_ostream &OS) { OS << "\n----- Found the following leaks -----\n"; - if (Leaks.empty()) { - OS << "No leaks found!\n"; - return; - } - - for (const auto &Leak : Leaks) { - OS << "At instruction\nIR : " << llvmIRToString(Leak.first) << '\n'; - OS << "\nLeak(s):\n"; - for (const auto *LeakedValue : Leak.second) { - OS << "IR : "; - // Get the actual leaked alloca instruction if possible - if (const auto *Load = llvm::dyn_cast(LeakedValue)) { - OS << llvmIRToString(Load->getPointerOperand()) << '\n'; - } else { - OS << llvmIRToString(LeakedValue) << '\n'; - } - } - OS << "-------------------\n"; - } + Printer->onFinalize(OS); } } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp index e71e30b0ea..04d8eba6ef 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp @@ -9,14 +9,13 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include -#include - using namespace std; using namespace psr; diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp new file mode 100644 index 0000000000..8f1dfb70fb --- /dev/null +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -0,0 +1,128 @@ +#include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/ExtendedTaintAnalysis/AbstractMemoryLocation.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h" +#include "phasar/PhasarLLVM/HelperAnalyses.h" +#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" +#include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" +#include "phasar/PhasarLLVM/TaintConfig/TaintConfigData.h" +#include "phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h" +#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" + +#include "llvm/ADT/DenseMap.h" + +#include "TestConfig.h" +#include "gtest/gtest.h" +using namespace psr; +using CallBackPairTy = std::pair::config_callback_t, + IDEExtendedTaintAnalysis<>::config_callback_t>; + +// Use template to variate between Typesate and Taint analysis +class GroundTruthCollector + : public DefaultAnalysisPrinter { +public: + // constructor init Groundtruth in each fixture + GroundTruthCollector(llvm::DenseMap> &GroundTruth) + : GroundTruth(GroundTruth){}; + + void findAndRemove(llvm::DenseMap> &Map1, + llvm::DenseMap> &Map2) { + for (auto Entry = Map1.begin(); Entry != Map1.end();) { + auto Iter = Map2.find(Entry->first); + if (Iter != Map2.end() && Iter->second == Entry->second) { + Map2.erase(Iter); + } + ++Entry; + } + } + + void onResult(Warning War) override { + llvm::DenseMap> FoundLeak; + int SinkId = stoi(getMetaDataID(War.Instr)); + std::set LeakedValueIds; + LeakedValueIds.insert(getMetaDataID((War.Fact)->base())); + FoundLeak.try_emplace(SinkId, LeakedValueIds); + findAndRemove(FoundLeak, GroundTruth); + } + + void onFinalize(llvm::raw_ostream & /*OS*/ = llvm::outs()) const override { + EXPECT_TRUE(GroundTruth.empty()); + } + +private: + llvm::DenseMap> GroundTruth{}; +}; + +class AnalysisPrinterTest : public ::testing::Test { +protected: + static constexpr auto PathToLlFiles = PHASAR_BUILD_SUBFOLDER("xtaint/"); + const std::vector EntryPoints = {"main"}; + + void doAnalysisTest( + llvm::StringRef IRFile, GroundTruthCollector >Printer, + std::variant Config) { + HelperAnalyses Helpers(PathToLlFiles + IRFile, EntryPoints); + + auto TConfig = std::visit( + Overloaded{[&](std::monostate) { + return LLVMTaintConfig(Helpers.getProjectIRDB()); + }, + [&](TaintConfigData *JS) { + auto Ret = LLVMTaintConfig(Helpers.getProjectIRDB(), *JS); + return Ret; + }, + [&](CallBackPairTy &&CB) { + return LLVMTaintConfig(std::move(CB.first), + std::move(CB.second)); + }}, + std::move(Config)); + + auto TaintProblem = createAnalysisProblem>( + Helpers, TConfig, EntryPoints); + + TaintProblem.setAnalysisPrinter(>Printer); + IDESolver Solver(TaintProblem, &Helpers.getICFG()); + Solver.solve(); + + TaintProblem.emitTextReport(Solver.getSolverResults()); + } +}; + +/* ============== BASIC TESTS ============== */ + +TEST_F(AnalysisPrinterTest, HandleBasicTest_01) { + llvm::DenseMap> GroundTruth; + GroundTruth[7] = {"0"}; + + TaintConfigData Config; + + FunctionData FuncDataMain; + FuncDataMain.Name = "main"; + FuncDataMain.SourceValues.push_back(0); + + FunctionData FuncDataPrint; + FuncDataPrint.Name = "_Z5printi"; + FuncDataPrint.SinkValues.push_back(0); + + Config.Functions.push_back(std::move(FuncDataMain)); + Config.Functions.push_back(std::move(FuncDataPrint)); + + GroundTruthCollector GroundTruthPrinter = {GroundTruth}; + doAnalysisTest("xtaint01_json_cpp_dbg.ll", GroundTruthPrinter, &Config); +} + +TEST_F(AnalysisPrinterTest, XTaint01) { + llvm::DenseMap> GroundTruth; + + GroundTruth[15] = {"8"}; + GroundTruthCollector GroundTruthPrinter = {GroundTruth}; + doAnalysisTest("xtaint01_cpp.ll", GroundTruthPrinter, std::monostate{}); +} + +// main function for the test case +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + return RUN_ALL_TESTS(); +} diff --git a/unittests/Utils/CMakeLists.txt b/unittests/Utils/CMakeLists.txt index 4edc79c483..fea979d614 100644 --- a/unittests/Utils/CMakeLists.txt +++ b/unittests/Utils/CMakeLists.txt @@ -6,6 +6,7 @@ set(UtilsSources LLVMShorthandsTest.cpp PAMMTest.cpp StableVectorTest.cpp + AnalysisPrinterTest.cpp ) if(PHASAR_ENABLE_DYNAMIC_LOG) From ec0abf4183e404264f125161a169bc16223b0243 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Tue, 31 Oct 2023 12:38:57 +0100 Subject: [PATCH 02/27] OnTheFlyReporting Initial Commit --- .../IfdsIde/Problems/IDETypeStateAnalysis.h | 2 +- .../PhasarLLVM/Utils/AnalysisPrinterBase.h | 2 +- .../PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 3 +- .../PhasarLLVM/Utils/NullAnalysisPrinter.h | 2 +- .../Utils/OnTheFlyAnalysisPrinter.h | 32 +++++++++++++++++++ .../Problems/IDEExtendedTaintAnalysis.cpp | 2 +- .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 2 +- unittests/Utils/AnalysisPrinterTest.cpp | 4 +-- 8 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index 866c21774c..fc4f541be6 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -553,7 +553,7 @@ class IDETypeStateAnalysis } } - this->Printer->onFinalize(OS); + this->Printer->onFinalize(); } private: diff --git a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h index 2e636396f8..595e14b1fb 100644 --- a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h +++ b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h @@ -28,7 +28,7 @@ template class AnalysisPrinterBase { public: virtual void onResult(Warning /*War*/) = 0; virtual void onInitialize() = 0; - virtual void onFinalize(llvm::raw_ostream & /*OS*/) const = 0; + virtual void onFinalize() const = 0; AnalysisPrinterBase() = default; virtual ~AnalysisPrinterBase() = default; diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h index a75f912eeb..7a230a5f93 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -25,7 +25,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { } void onInitialize() override{}; - void onFinalize(llvm::raw_ostream &OS = llvm::outs()) const override { + void onFinalize() const override { for (const auto &Iter : AnalysisResults.War) { OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; @@ -40,6 +40,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { private: Results AnalysisResults{}; + llvm::raw_ostream &OS = llvm::outs(); }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h index 9007677557..03bf14439c 100644 --- a/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h @@ -15,7 +15,7 @@ class NullAnalysisPrinter final : public AnalysisPrinterBase { void onInitialize() override{}; void onResult(Warning /*War*/) override{}; - void onFinalize(llvm::raw_ostream & /*OS*/) const override{}; + void onFinalize() const override{}; private: NullAnalysisPrinter() = default; diff --git a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h new file mode 100644 index 0000000000..47d9ad6405 --- /dev/null +++ b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h @@ -0,0 +1,32 @@ +#ifndef PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H +#define PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H + +#include "phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h" +namespace psr { + +template +class OnTheFlyAnalysisPrinter + : public DefaultAnalysisPrinter { + using l_t = typename AnalysisDomainTy::l_t; + +public: + OnTheFlyAnalysisPrinter() = default; + + void onInitialize() override{}; + void onResult(Warning War) override { + + OS << "\nAt IR statement: " << NToString(War.Instr) << "\n"; + OS << "\tFact: " << DToString(War.Fact) << "\n"; + if constexpr (std::is_same_v) { + OS << "Value: " << LToString(War.LatticeElement) << "\n"; + } + } + + void onFinalize() const override{}; + +private: + llvm::raw_ostream &OS = llvm::outs(); +}; +} // namespace psr + +#endif diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index e6b3cc32ab..1de67d0251 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -760,7 +760,7 @@ void IDEExtendedTaintAnalysis::emitTextReport( } } - Printer->onFinalize(OS); + Printer->onFinalize(); } // Helpers: diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index 18ff4434c3..69a2de8a09 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -487,7 +487,7 @@ void IFDSTaintAnalysis::emitTextReport( const SolverResults & /*SR*/, llvm::raw_ostream &OS) { OS << "\n----- Found the following leaks -----\n"; - Printer->onFinalize(OS); + Printer->onFinalize(); } } // namespace psr diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index 8f1dfb70fb..b061c43a47 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -47,9 +47,7 @@ class GroundTruthCollector findAndRemove(FoundLeak, GroundTruth); } - void onFinalize(llvm::raw_ostream & /*OS*/ = llvm::outs()) const override { - EXPECT_TRUE(GroundTruth.empty()); - } + void onFinalize() const override { EXPECT_TRUE(GroundTruth.empty()); } private: llvm::DenseMap> GroundTruth{}; From 6063730526f6f30578da72f49b5756ff07d9e75e Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Mon, 20 Nov 2023 13:11:09 +0100 Subject: [PATCH 03/27] fix: review feedback --- .../DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h | 8 ++++---- .../phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h | 2 +- .../phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 2 +- .../IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp | 10 +++++----- .../DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp | 12 ++++++------ 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index 866c21774c..19bdd525a0 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -530,9 +530,9 @@ class IDETypeStateAnalysis llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { Warning> - War(&I, Res.first, TSD->error()); + Warn(&I, Res.first, TSD->error()); // ERROR STATE DETECTED - this->Printer->onResult(War); + this->Printer->onResult(Warn); } } } @@ -542,9 +542,9 @@ class IDETypeStateAnalysis llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { Warning> - War(&I, Res.first, TSD->error()); + Warn(&I, Res.first, TSD->error()); // ERROR STATE DETECTED - this->Printer->onResult(War); + this->Printer->onResult(Warn); } } } diff --git a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h index 2e636396f8..9190ead074 100644 --- a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h +++ b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h @@ -20,7 +20,7 @@ template struct Warning { LatticeElement(std::move(Lattice)) {} }; -template struct Results { +template struct DataflowAnalysisResults { std::vector> War; }; diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h index a75f912eeb..7cbdf476b0 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -39,7 +39,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { } private: - Results AnalysisResults{}; + DataflowAnalysisResults AnalysisResults{}; }; } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index d57bd1303f..6759ed4b95 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -227,9 +227,9 @@ void IDEExtendedTaintAnalysis::reportLeakIfNecessary( const llvm::Value *LeakCandidate) { if (isSink(SinkCandidate, Inst)) { Leaks[Inst].insert(LeakCandidate); - Warning War( + Warning Warn( Inst, makeFlowFact(LeakCandidate), Top{}); - Printer->onResult(War); + Printer->onResult(Warn); } } @@ -754,9 +754,9 @@ void IDEExtendedTaintAnalysis::emitTextReport( for (auto &[Inst, LeakSet] : Leaks) { for (const auto &Leak : LeakSet) { - Warning War(Inst, makeFlowFact(Leak), - Top{}); - Printer->onResult(War); + Warning Warn(Inst, makeFlowFact(Leak), + Top{}); + Printer->onResult(Warn); } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index 18ff4434c3..a6ee4458b6 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -410,9 +410,9 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, CallSite](d_t Source) -> container_type { if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Warning War(CallSite, Source, - topElement()); - Printer->onResult(War); + Warning Warn(CallSite, Source, + topElement()); + Printer->onResult(Warn); } } @@ -439,9 +439,9 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Warning War(CallSite, Source, - topElement()); - Printer->onResult(War); + Warning Warn(CallSite, Source, + topElement()); + Printer->onResult(Warn); } } From b30ceeeeefde8c6e9501c19aee53b86791e33de1 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Fri, 24 Nov 2023 10:05:54 +0100 Subject: [PATCH 04/27] onTheFlyAnalysis makeUniquePtr --- .../PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 2 +- .../PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h | 14 +++++++++----- .../IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h index 7a230a5f93..7784ff8318 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -18,7 +18,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { public: ~DefaultAnalysisPrinter() override = default; - DefaultAnalysisPrinter() = default; + DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(OS) {} void onResult(Warning War) override { AnalysisResults.War.emplace_back(std::move(War)); diff --git a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h index 47d9ad6405..4158c43a97 100644 --- a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h @@ -2,6 +2,9 @@ #define PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H #include "phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h" +#include "phasar/Utils/MaybeUniquePtr.h" + +#include namespace psr { template @@ -10,22 +13,23 @@ class OnTheFlyAnalysisPrinter using l_t = typename AnalysisDomainTy::l_t; public: - OnTheFlyAnalysisPrinter() = default; + OnTheFlyAnalysisPrinter(llvm::raw_ostream *OS) + : DefaultAnalysisPrinter(OS), OS(OS){}; void onInitialize() override{}; void onResult(Warning War) override { - OS << "\nAt IR statement: " << NToString(War.Instr) << "\n"; - OS << "\tFact: " << DToString(War.Fact) << "\n"; + *OS << "\nAt IR statement: " << NToString(War.Instr) << "\n"; + *OS << "\tFact: " << DToString(War.Fact) << "\n"; if constexpr (std::is_same_v) { - OS << "Value: " << LToString(War.LatticeElement) << "\n"; + *OS << "Value: " << LToString(War.LatticeElement) << "\n"; } } void onFinalize() const override{}; private: - llvm::raw_ostream &OS = llvm::outs(); + MaybeUniquePtr OS; }; } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index 1de67d0251..6b8ee8fc87 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -20,6 +20,7 @@ #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" #include "phasar/Pointer/PointsToInfo.h" #include "phasar/Utils/DebugOutput.h" #include "phasar/Utils/Logger.h" From 51e60a1dcb615b454822e553ba7606da954e21c3 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Tue, 31 Oct 2023 12:38:57 +0100 Subject: [PATCH 05/27] OnTheFlyReporting Initial Commit --- .../IfdsIde/Problems/IDETypeStateAnalysis.h | 2 +- .../PhasarLLVM/Utils/AnalysisPrinterBase.h | 2 +- .../PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 3 +- .../PhasarLLVM/Utils/NullAnalysisPrinter.h | 2 +- .../Utils/OnTheFlyAnalysisPrinter.h | 32 +++++++++++++++++++ .../Problems/IDEExtendedTaintAnalysis.cpp | 2 +- .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 2 +- unittests/Utils/AnalysisPrinterTest.cpp | 4 +-- 8 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index 19bdd525a0..134efaec8f 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -553,7 +553,7 @@ class IDETypeStateAnalysis } } - this->Printer->onFinalize(OS); + this->Printer->onFinalize(); } private: diff --git a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h index 9190ead074..eb98bc11ab 100644 --- a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h +++ b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h @@ -28,7 +28,7 @@ template class AnalysisPrinterBase { public: virtual void onResult(Warning /*War*/) = 0; virtual void onInitialize() = 0; - virtual void onFinalize(llvm::raw_ostream & /*OS*/) const = 0; + virtual void onFinalize() const = 0; AnalysisPrinterBase() = default; virtual ~AnalysisPrinterBase() = default; diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h index 7cbdf476b0..e41364fec2 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -25,7 +25,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { } void onInitialize() override{}; - void onFinalize(llvm::raw_ostream &OS = llvm::outs()) const override { + void onFinalize() const override { for (const auto &Iter : AnalysisResults.War) { OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; @@ -40,6 +40,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { private: DataflowAnalysisResults AnalysisResults{}; + llvm::raw_ostream &OS = llvm::outs(); }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h index 9007677557..03bf14439c 100644 --- a/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h @@ -15,7 +15,7 @@ class NullAnalysisPrinter final : public AnalysisPrinterBase { void onInitialize() override{}; void onResult(Warning /*War*/) override{}; - void onFinalize(llvm::raw_ostream & /*OS*/) const override{}; + void onFinalize() const override{}; private: NullAnalysisPrinter() = default; diff --git a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h new file mode 100644 index 0000000000..47d9ad6405 --- /dev/null +++ b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h @@ -0,0 +1,32 @@ +#ifndef PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H +#define PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H + +#include "phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h" +namespace psr { + +template +class OnTheFlyAnalysisPrinter + : public DefaultAnalysisPrinter { + using l_t = typename AnalysisDomainTy::l_t; + +public: + OnTheFlyAnalysisPrinter() = default; + + void onInitialize() override{}; + void onResult(Warning War) override { + + OS << "\nAt IR statement: " << NToString(War.Instr) << "\n"; + OS << "\tFact: " << DToString(War.Fact) << "\n"; + if constexpr (std::is_same_v) { + OS << "Value: " << LToString(War.LatticeElement) << "\n"; + } + } + + void onFinalize() const override{}; + +private: + llvm::raw_ostream &OS = llvm::outs(); +}; +} // namespace psr + +#endif diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index 6759ed4b95..73db61ae84 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -760,7 +760,7 @@ void IDEExtendedTaintAnalysis::emitTextReport( } } - Printer->onFinalize(OS); + Printer->onFinalize(); } // Helpers: diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index a6ee4458b6..e634961926 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -487,7 +487,7 @@ void IFDSTaintAnalysis::emitTextReport( const SolverResults & /*SR*/, llvm::raw_ostream &OS) { OS << "\n----- Found the following leaks -----\n"; - Printer->onFinalize(OS); + Printer->onFinalize(); } } // namespace psr diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index 8f1dfb70fb..b061c43a47 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -47,9 +47,7 @@ class GroundTruthCollector findAndRemove(FoundLeak, GroundTruth); } - void onFinalize(llvm::raw_ostream & /*OS*/ = llvm::outs()) const override { - EXPECT_TRUE(GroundTruth.empty()); - } + void onFinalize() const override { EXPECT_TRUE(GroundTruth.empty()); } private: llvm::DenseMap> GroundTruth{}; From 07b57dfa848b12ab9a1ba516f269ddc7dcf3f282 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Fri, 24 Nov 2023 10:05:54 +0100 Subject: [PATCH 06/27] onTheFlyAnalysis makeUniquePtr --- .../PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 2 +- .../PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h | 14 +++++++++----- .../IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h index e41364fec2..29e68b3651 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -18,7 +18,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { public: ~DefaultAnalysisPrinter() override = default; - DefaultAnalysisPrinter() = default; + DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(OS) {} void onResult(Warning War) override { AnalysisResults.War.emplace_back(std::move(War)); diff --git a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h index 47d9ad6405..4158c43a97 100644 --- a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h @@ -2,6 +2,9 @@ #define PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H #include "phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h" +#include "phasar/Utils/MaybeUniquePtr.h" + +#include namespace psr { template @@ -10,22 +13,23 @@ class OnTheFlyAnalysisPrinter using l_t = typename AnalysisDomainTy::l_t; public: - OnTheFlyAnalysisPrinter() = default; + OnTheFlyAnalysisPrinter(llvm::raw_ostream *OS) + : DefaultAnalysisPrinter(OS), OS(OS){}; void onInitialize() override{}; void onResult(Warning War) override { - OS << "\nAt IR statement: " << NToString(War.Instr) << "\n"; - OS << "\tFact: " << DToString(War.Fact) << "\n"; + *OS << "\nAt IR statement: " << NToString(War.Instr) << "\n"; + *OS << "\tFact: " << DToString(War.Fact) << "\n"; if constexpr (std::is_same_v) { - OS << "Value: " << LToString(War.LatticeElement) << "\n"; + *OS << "Value: " << LToString(War.LatticeElement) << "\n"; } } void onFinalize() const override{}; private: - llvm::raw_ostream &OS = llvm::outs(); + MaybeUniquePtr OS; }; } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index 73db61ae84..e6f81bdd03 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -20,6 +20,7 @@ #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" #include "phasar/Pointer/PointsToInfo.h" #include "phasar/Utils/DebugOutput.h" #include "phasar/Utils/Logger.h" From af3757a7c4bedab1d235bb3487691ec02b146f9e Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Sat, 2 Dec 2023 02:29:52 +0100 Subject: [PATCH 07/27] addressing minor error in prev commit --- .../DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index db689c493a..e6f81bdd03 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -762,8 +762,6 @@ void IDEExtendedTaintAnalysis::emitTextReport( } Printer->onFinalize(); - - Printer->onFinalize(); } // Helpers: From 63c27c6b19676e058488a3764906f86c62b6e47d Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Mon, 11 Dec 2023 23:01:49 +0100 Subject: [PATCH 08/27] Refactoring Warn Variable and Refactoring lambda flow for AnalysisPrinter --- .../PhasarLLVM/Utils/AnalysisPrinterBase.h | 4 +- .../PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 6 +-- .../Utils/OnTheFlyAnalysisPrinter.h | 32 ++++++++---- .../Problems/IFDSUninitializedVariables.cpp | 51 ++++++++----------- unittests/Utils/AnalysisPrinterTest.cpp | 6 +-- 5 files changed, 51 insertions(+), 48 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h index eb98bc11ab..ae8264a7cc 100644 --- a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h +++ b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h @@ -21,12 +21,12 @@ template struct Warning { }; template struct DataflowAnalysisResults { - std::vector> War; + std::vector> Warn; }; template class AnalysisPrinterBase { public: - virtual void onResult(Warning /*War*/) = 0; + virtual void onResult(Warning /*Warn*/) = 0; virtual void onInitialize() = 0; virtual void onFinalize() const = 0; diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h index 29e68b3651..4ad4f59bc4 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -20,13 +20,13 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { ~DefaultAnalysisPrinter() override = default; DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(OS) {} - void onResult(Warning War) override { - AnalysisResults.War.emplace_back(std::move(War)); + void onResult(Warning Warn) override { + AnalysisResults.Warn.emplace_back(std::move(Warn)); } void onInitialize() override{}; void onFinalize() const override { - for (const auto &Iter : AnalysisResults.War) { + for (const auto &Iter : AnalysisResults.Warn) { OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; diff --git a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h index 4158c43a97..eebd56451a 100644 --- a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h @@ -1,35 +1,45 @@ #ifndef PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H #define PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H -#include "phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h" +#include "phasar/Domain/BinaryDomain.h" +#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/Utils/IO.h" #include "phasar/Utils/MaybeUniquePtr.h" +#include + +#include #include namespace psr { template -class OnTheFlyAnalysisPrinter - : public DefaultAnalysisPrinter { +class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { using l_t = typename AnalysisDomainTy::l_t; public: - OnTheFlyAnalysisPrinter(llvm::raw_ostream *OS) - : DefaultAnalysisPrinter(OS), OS(OS){}; + explicit OnTheFlyAnalysisPrinter(llvm::raw_ostream &OS) + : AnalysisPrinterBase(), OS(&OS){}; - void onInitialize() override{}; - void onResult(Warning War) override { + explicit OnTheFlyAnalysisPrinter( + const llvm::Twine &Filename) + : AnalysisPrinterBase(), OS(openFileStream(Filename)){}; - *OS << "\nAt IR statement: " << NToString(War.Instr) << "\n"; - *OS << "\tFact: " << DToString(War.Fact) << "\n"; + void onInitialize() override{}; + void onResult(Warning Warn) override { + assert(isValid()); + *OS << "\nAt IR statement: " << NToString(Warn.Instr) << "\n"; + *OS << "\tFact: " << DToString(Warn.Fact) << "\n"; if constexpr (std::is_same_v) { - *OS << "Value: " << LToString(War.LatticeElement) << "\n"; + *OS << "Value: " << LToString(Warn.LatticeElement) << "\n"; } } void onFinalize() const override{}; + bool isValid() { return OS != nullptr; } + private: - MaybeUniquePtr OS; + MaybeUniquePtr OS = nullptr; }; } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp index 7dea9e963b..c00eae3381 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp @@ -188,38 +188,30 @@ IFDSUninitializedVariables::getNormalFlowFunction( }); } // check if some instruction is using an undefined value (in)directly - struct UVFF : FlowFunction { - const llvm::Instruction *Inst; - std::map> &UndefValueUses; - UVFF(const llvm::Instruction *Inst, - std::map> &UVU) - : Inst(Inst), UndefValueUses(UVU) {} - std::set - computeTargets(IFDSUninitializedVariables::d_t Source) override { - for (const auto &Operand : Inst->operands()) { - const llvm::UndefValue *Undef = - llvm::dyn_cast(Operand); - if (Operand == Source || Operand == Undef) { - //---------------------------------------------------------------- - // It is not necessary and (from my point of view) not intended to - // report a leak on EVERY kind of instruction. - // For some of them (e.g. gep, bitcast, ...) propagating the dataflow - // facts may be enough - //---------------------------------------------------------------- - if (!llvm::isa(Inst) && - !llvm::isa(Inst) && - !llvm::isa(Inst)) { - UndefValueUses[Inst].insert(Operand); - } - return {Source, Inst}; + + return lambdaFlow([Curr, this](d_t Source) -> std::set { + for (const auto &Operand : Curr->operands()) { + const llvm::UndefValue *Undef = llvm::dyn_cast(Operand); + if (Operand == Source || Operand == Undef) { + //---------------------------------------------------------------- + // It is not necessary and (from my point of view) not intended to + // report a leak on EVERY kind of instruction. + // For some of them (e.g. gep, bitcast, ...) propagating the dataflow + // facts may be enough + //---------------------------------------------------------------- + if (!llvm::isa(Curr) && + !llvm::isa(Curr) && + !llvm::isa(Curr)) { + UndefValueUses[Curr].insert(Operand); + Warning Warn(Curr, Operand, + BinaryDomain::TOP); + Printer->onResult(Warn); } + return {Source, Curr}; } - return {Source}; } - }; - return std::make_shared(Curr, UndefValueUses); + return {Source}; + }); } IFDSUninitializedVariables::FlowFunctionPtrType @@ -441,6 +433,7 @@ void IFDSUninitializedVariables::emitTextReport( Res.print(OS); } } + Printer->onFinalize(); } } diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index b061c43a47..a0941825e2 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -38,11 +38,11 @@ class GroundTruthCollector } } - void onResult(Warning War) override { + void onResult(Warning Warn) override { llvm::DenseMap> FoundLeak; - int SinkId = stoi(getMetaDataID(War.Instr)); + int SinkId = stoi(getMetaDataID(Warn.Instr)); std::set LeakedValueIds; - LeakedValueIds.insert(getMetaDataID((War.Fact)->base())); + LeakedValueIds.insert(getMetaDataID((Warn.Fact)->base())); FoundLeak.try_emplace(SinkId, LeakedValueIds); findAndRemove(FoundLeak, GroundTruth); } From 24f91da215940e74b4ce62466ff7d94ac8248e9c Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Wed, 20 Dec 2023 16:28:20 +0100 Subject: [PATCH 09/27] Integrating sourceMgr to AnalysisPrinter --- .../PhasarLLVM/Utils/SourceMgrPrinter.h | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h new file mode 100644 index 0000000000..8d4e9431fa --- /dev/null +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -0,0 +1,51 @@ +#ifndef PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H +#define PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H +#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" +#include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" + +#include "llvm/Support/MemoryBuffer.h" + +#include +#include + +namespace psr { +template +class SourceMgrPrinter : public OnTheFlyAnalysisPrinter { +public: + SourceMgrPrinter() = default; + + void onInitialize() override {} + void onFinalize() const override{}; + void onResult(Warning Warn) override { + + SrcMgr.PrintMessage(SrcMgr.FindLocForLineAndColumn( + getSourceBufId(getFilePathFromIR(Warn.Fact)), + getLineAndColFromIR(Warn.Fact).first, + getLineAndColFromIR(Warn.Fact).second), + llvm::SourceMgr::DK_Warning, Msg); + } + + std::optional getSourceBufId(llvm::StringRef FileName) { + if (auto It = FileNameIDMap.find(FileName); It != FileNameIDMap.end()) { + return It->second; + } + + auto Buf = llvm::MemoryBuffer::getFile(FileName, true); + if (!Buf) { + FileNameIDMap.try_emplace(FileName, std::nullopt); + return std::nullopt; + } + + auto Id = SrcMgr.AddNewSourceBuffer(std::move(Buf.get()), llvm::SMLoc{}); + FileNameIDMap.try_emplace(FileName, Id); + return Id; + } + +private: + llvm::SourceMgr SrcMgr; + llvm::StringMap FileNameIDMap; + static constexpr llvm::StringLiteral Msg = "Phasar found an error"; +}; +} // namespace psr +#endif From 2d27f5e2d44939d81f2c6e53ae563844aea163bd Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Wed, 3 Jan 2024 15:54:28 +0100 Subject: [PATCH 10/27] Testcase for OnTheFlyAnalysisPrinting --- .../Utils/OnTheFlyAnalysisPrinter.h | 4 + unittests/Utils/CMakeLists.txt | 1 + .../Utils/OnTheFlyAnalysisPrinterTest.cpp | 103 ++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp diff --git a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h index eebd56451a..729d78269f 100644 --- a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h @@ -5,6 +5,7 @@ #include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" #include "phasar/Utils/IO.h" #include "phasar/Utils/MaybeUniquePtr.h" +#include "phasar/Utils/Printer.h" #include @@ -24,6 +25,9 @@ class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { const llvm::Twine &Filename) : AnalysisPrinterBase(), OS(openFileStream(Filename)){}; + OnTheFlyAnalysisPrinter() = default; + ~OnTheFlyAnalysisPrinter() = default; + void onInitialize() override{}; void onResult(Warning Warn) override { assert(isValid()); diff --git a/unittests/Utils/CMakeLists.txt b/unittests/Utils/CMakeLists.txt index fea979d614..3485b1eff5 100644 --- a/unittests/Utils/CMakeLists.txt +++ b/unittests/Utils/CMakeLists.txt @@ -7,6 +7,7 @@ set(UtilsSources PAMMTest.cpp StableVectorTest.cpp AnalysisPrinterTest.cpp + OnTheFlyAnalysisPrinterTest.cpp ) if(PHASAR_ENABLE_DYNAMIC_LOG) diff --git a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp new file mode 100644 index 0000000000..45baf161de --- /dev/null +++ b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp @@ -0,0 +1,103 @@ +#include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" + +#include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h" +#include "phasar/PhasarLLVM/HelperAnalyses.h" +#include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" +#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/PhasarLLVM/Utils/SourceMgrPrinter.h" + +#include "llvm/ADT/DenseMap.h" + +#include "TestConfig.h" +#include "gtest/gtest.h" + +#include +#include + +using namespace psr; + +class GroundTruthCollector + : public OnTheFlyAnalysisPrinter { +public: + // constructor init Groundtruth in each fixture + GroundTruthCollector(llvm::DenseMap> &GroundTruth) + : GroundTruth(GroundTruth){}; + + void findAndRemove(llvm::DenseMap> &Map1, + llvm::DenseMap> &Map2) { + for (auto Entry = Map1.begin(); Entry != Map1.end();) { + auto Iter = Map2.find(Entry->first); + if (Iter != Map2.end() && Iter->second == Entry->second) { + Map2.erase(Iter); + } + ++Entry; + } + } + + void onResult(Warning Warn) override { + llvm::DenseMap> FoundLeak; + int SinkId = stoi(getMetaDataID(Warn.Instr)); + std::set LeakedValueIds; + LeakedValueIds.insert(getMetaDataID((Warn.Fact))); + FoundLeak.try_emplace(SinkId, LeakedValueIds); + findAndRemove(FoundLeak, GroundTruth); + } + + void onFinalize() const override { EXPECT_TRUE(GroundTruth.empty()); } + +private: + llvm::DenseMap> GroundTruth{}; +}; + +class OnTheFlyAnalysisPrinterTest : public ::testing::Test { +protected: + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SUBFOLDER("uninitialized_variables/"); + + const std::vector EntryPoints = {"main"}; + std::optional UnInitProblem; + std::optional HA; + + void initialize(const llvm::Twine &IRFile) { + HA.emplace(PathToLlFiles + IRFile, EntryPoints); + UnInitProblem = + createAnalysisProblem(*HA, EntryPoints); + } + + void doAnalysisTest(llvm::StringRef IRFile, GroundTruthCollector >Printer) { + initialize(IRFile); + UnInitProblem->setAnalysisPrinter(>Printer); + IFDSSolver Solver(*UnInitProblem, &HA->getICFG()); + Solver.solve(); + GTPrinter.onFinalize(); + } +}; + +/* ============== BASIC TESTS ============== */ + +TEST_F(OnTheFlyAnalysisPrinterTest, UninitTest_01_LEAK) { + + llvm::DenseMap> GroundTruth; + // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i + GroundTruth[6] = {"1"}; + // %5 = add nsw i32 %4, 10 ; %4 is undef, since it is loaded from + // undefined alloca; not sure if it is necessary to report again + GroundTruth[7] = {"6"}; + + GroundTruthCollector GroundTruthPrinter = {GroundTruth}; + doAnalysisTest("binop_uninit_cpp_dbg.ll", GroundTruthPrinter); +} + +TEST_F(OnTheFlyAnalysisPrinterTest, UninitTest_02_NOLEAK) { + llvm::DenseMap> GroundTruth; + GroundTruthCollector GroundTruthPrinter = {GroundTruth}; + doAnalysisTest("ctor_default_cpp_dbg.ll", GroundTruthPrinter); +} + +// main function for the test case +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + return RUN_ALL_TESTS(); +} From b874c0564234862c18fc4138c56e7a8ab9095fe1 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Tue, 9 Jan 2024 13:40:37 +0100 Subject: [PATCH 11/27] Testcase for SourceMgrPrinter --- .../PhasarLLVM/Utils/SourceMgrPrinter.h | 23 ++-- unittests/Utils/CMakeLists.txt | 1 + unittests/Utils/SourceMgrPrinterTest.cpp | 107 ++++++++++++++++++ 3 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 unittests/Utils/SourceMgrPrinterTest.cpp diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 8d4e9431fa..58dd94ca81 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -3,27 +3,33 @@ #include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" +#include "phasar/Utils/Logger.h" #include "llvm/Support/MemoryBuffer.h" #include #include +#include namespace psr { template -class SourceMgrPrinter : public OnTheFlyAnalysisPrinter { +class SourceMgrPrinter : public AnalysisPrinterBase { public: SourceMgrPrinter() = default; + SourceMgrPrinter(llvm::raw_ostream &OS) : OS(OS){}; void onInitialize() override {} void onFinalize() const override{}; void onResult(Warning Warn) override { - - SrcMgr.PrintMessage(SrcMgr.FindLocForLineAndColumn( - getSourceBufId(getFilePathFromIR(Warn.Fact)), - getLineAndColFromIR(Warn.Fact).first, - getLineAndColFromIR(Warn.Fact).second), - llvm::SourceMgr::DK_Warning, Msg); + auto BufIdOpt = getSourceBufId(getFilePathFromIR(Warn.Instr)); + if (BufIdOpt.has_value()) { + SrcMgr.PrintMessage(OS, + SrcMgr.FindLocForLineAndColumn( + BufIdOpt.value(), + getLineAndColFromIR(Warn.Instr).first, + getLineAndColFromIR(Warn.Instr).second), + llvm::SourceMgr::DK_Warning, Msg); + } } std::optional getSourceBufId(llvm::StringRef FileName) { @@ -33,7 +39,7 @@ class SourceMgrPrinter : public OnTheFlyAnalysisPrinter { auto Buf = llvm::MemoryBuffer::getFile(FileName, true); if (!Buf) { - FileNameIDMap.try_emplace(FileName, std::nullopt); + PHASAR_LOG_LEVEL(WARNING, "File not accessible: " << FileName); return std::nullopt; } @@ -46,6 +52,7 @@ class SourceMgrPrinter : public OnTheFlyAnalysisPrinter { llvm::SourceMgr SrcMgr; llvm::StringMap FileNameIDMap; static constexpr llvm::StringLiteral Msg = "Phasar found an error"; + llvm::raw_ostream &OS = llvm::errs(); }; } // namespace psr #endif diff --git a/unittests/Utils/CMakeLists.txt b/unittests/Utils/CMakeLists.txt index 3485b1eff5..60fa49cf43 100644 --- a/unittests/Utils/CMakeLists.txt +++ b/unittests/Utils/CMakeLists.txt @@ -8,6 +8,7 @@ set(UtilsSources StableVectorTest.cpp AnalysisPrinterTest.cpp OnTheFlyAnalysisPrinterTest.cpp + SourceMgrPrinterTest.cpp ) if(PHASAR_ENABLE_DYNAMIC_LOG) diff --git a/unittests/Utils/SourceMgrPrinterTest.cpp b/unittests/Utils/SourceMgrPrinterTest.cpp new file mode 100644 index 0000000000..985aff708f --- /dev/null +++ b/unittests/Utils/SourceMgrPrinterTest.cpp @@ -0,0 +1,107 @@ +#include "phasar/PhasarLLVM/Utils/SourceMgrPrinter.h" + +#include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h" +#include "phasar/PhasarLLVM/HelperAnalyses.h" +#include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" +#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" + +#include "TestConfig.h" +#include "gtest/gtest.h" + +#include + +#include +#include + +using namespace psr; + +class GroundTruthCollector + : public SourceMgrPrinter { +public: + // constructor init Groundtruth in each fixture + GroundTruthCollector(std::set &GroundTruth) + : SourceMgrPrinter(OS), + GroundTruth(GroundTruth), OS(Str){}; + + std::string findSubString(const std::string &String) { + size_t LastSlashPos = String.rfind('/'); + if (LastSlashPos != std::string::npos) { + // Find the first space after the last '/' + size_t FirstSpacePos = String.find(' ', LastSlashPos); + + if (FirstSpacePos != std::string::npos) { + // Extract the substring from the last '/' to the first space after + // the last '/' + std::string Result = + String.substr(LastSlashPos + 1, FirstSpacePos - LastSlashPos - 2); + return Result; + } + return ""; + } + return ""; + } + + void findAndRemove(const std::string &SearchString) { + std::string SubString = findSubString(SearchString); + GroundTruth.erase(SubString); + } + + void onResult(Warning Warn) override { + SourceMgrPrinter::onResult(Warn); + findAndRemove(OS.str()); + } + + void onFinalize() const override { EXPECT_TRUE(GroundTruth.empty()); } + +private: + std::set GroundTruth{}; + std::string Str; + llvm::raw_string_ostream OS; +}; + +class SourceMgrPrinterTest : public ::testing::Test { +protected: + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SUBFOLDER("uninitialized_variables/"); + + const std::vector EntryPoints = {"main"}; + std::optional UnInitProblem; + std::optional HA; + + void initialize(const llvm::Twine &IRFile) { + HA.emplace(PathToLlFiles + IRFile, EntryPoints); + UnInitProblem = + createAnalysisProblem(*HA, EntryPoints); + } + + void doAnalysisTest( + llvm::StringRef IRFile, + AnalysisPrinterBase >Printer) { + initialize(IRFile); + UnInitProblem->setAnalysisPrinter(>Printer); + IFDSSolver Solver(*UnInitProblem, &HA->getICFG()); + Solver.solve(); + GTPrinter.onFinalize(); + } +}; + +/* ============== BASIC TESTS ============== */ + +TEST_F(SourceMgrPrinterTest, UninitTest_01_LEAK) { + + std::set GroundTruth; + + GroundTruth = {"binop_uninit.cpp:3:11", "binop_uninit.cpp:3:13"}; + + GroundTruthCollector GroundTruthPrinter = {GroundTruth}; + + doAnalysisTest("binop_uninit_cpp_dbg.ll", GroundTruthPrinter); +} + +// main function for the test case +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + return RUN_ALL_TESTS(); +} From 2a28822733ff2c78655ecd7deaff130321d53317 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Tue, 9 Jan 2024 14:18:17 +0100 Subject: [PATCH 12/27] MaybeUniquePtr for SourceMgrPrinter --- include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 58dd94ca81..82aa8814cf 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -4,6 +4,7 @@ #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" #include "phasar/Utils/Logger.h" +#include "phasar/Utils/MaybeUniquePtr.h" #include "llvm/Support/MemoryBuffer.h" @@ -16,14 +17,14 @@ template class SourceMgrPrinter : public AnalysisPrinterBase { public: SourceMgrPrinter() = default; - SourceMgrPrinter(llvm::raw_ostream &OS) : OS(OS){}; + SourceMgrPrinter(llvm::raw_ostream &OS) : OS(&OS){}; void onInitialize() override {} void onFinalize() const override{}; void onResult(Warning Warn) override { auto BufIdOpt = getSourceBufId(getFilePathFromIR(Warn.Instr)); if (BufIdOpt.has_value()) { - SrcMgr.PrintMessage(OS, + SrcMgr.PrintMessage(*OS, SrcMgr.FindLocForLineAndColumn( BufIdOpt.value(), getLineAndColFromIR(Warn.Instr).first, @@ -52,7 +53,7 @@ class SourceMgrPrinter : public AnalysisPrinterBase { llvm::SourceMgr SrcMgr; llvm::StringMap FileNameIDMap; static constexpr llvm::StringLiteral Msg = "Phasar found an error"; - llvm::raw_ostream &OS = llvm::errs(); + MaybeUniquePtr OS = &llvm::errs(); }; } // namespace psr #endif From 0341768fe897e164d836ace7c7815ed58587e1fd Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Sat, 3 Feb 2024 09:20:11 +0100 Subject: [PATCH 13/27] Minor review comments --- .../IfdsIde/Problems/IDETypeStateAnalysis.h | 7 +++++-- .../PhasarLLVM/Utils/AnalysisPrinterBase.h | 8 ++++++-- .../PhasarLLVM/Utils/DefaultAnalysisPrinter.h | 11 ++++++----- .../phasar/PhasarLLVM/Utils/SourceMgrPrinter.h | 16 +++++++++------- .../Problems/IDEExtendedTaintAnalysis.cpp | 10 ++++++---- .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 11 +++++++---- .../Problems/IFDSUninitializedVariables.cpp | 6 ++++-- 7 files changed, 43 insertions(+), 26 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index 134efaec8f..559620dc62 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -19,6 +19,7 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h" #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/Utils/ByRef.h" #include "phasar/Utils/JoinLattice.h" #include "phasar/Utils/Logger.h" @@ -530,7 +531,8 @@ class IDETypeStateAnalysis llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { Warning> - Warn(&I, Res.first, TSD->error()); + Warn(&I, Res.first, TSD->error(), + DataFlowAnalysisType::None); // ERROR STATE DETECTED this->Printer->onResult(Warn); } @@ -542,7 +544,8 @@ class IDETypeStateAnalysis llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { Warning> - Warn(&I, Res.first, TSD->error()); + Warn(&I, Res.first, TSD->error(), + DataFlowAnalysisType::None); // ERROR STATE DETECTED this->Printer->onResult(Warn); } diff --git a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h index ae8264a7cc..2318f95e82 100644 --- a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h +++ b/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h @@ -1,6 +1,8 @@ #ifndef PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H #define PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" + #include "llvm/Support/raw_ostream.h" namespace psr { @@ -13,11 +15,13 @@ template struct Warning { n_t Instr; d_t Fact; l_t LatticeElement; + DataFlowAnalysisType AnalysisType; // Constructor - Warning(n_t Inst, d_t DfFact, l_t Lattice) + Warning(n_t Inst, d_t DfFact, l_t Lattice, + DataFlowAnalysisType DfAnalysisType) : Instr(std::move(Inst)), Fact(std::move(DfFact)), - LatticeElement(std::move(Lattice)) {} + LatticeElement(std::move(Lattice)), AnalysisType(DfAnalysisType) {} }; template struct DataflowAnalysisResults { diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h index 4ad4f59bc4..4f7e236762 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h @@ -4,6 +4,7 @@ #include "phasar/Domain/BinaryDomain.h" #include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/MaybeUniquePtr.h" #include "phasar/Utils/Printer.h" #include @@ -18,7 +19,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { public: ~DefaultAnalysisPrinter() override = default; - DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(OS) {} + DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(&OS) {} void onResult(Warning Warn) override { AnalysisResults.Warn.emplace_back(std::move(Warn)); @@ -28,19 +29,19 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { void onFinalize() const override { for (const auto &Iter : AnalysisResults.Warn) { - OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; + *OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; - OS << "\tFact: " << DToString(Iter.Fact) << "\n"; + *OS << "\tFact: " << DToString(Iter.Fact) << "\n"; if constexpr (std::is_same_v) { - OS << "Value: " << LToString(Iter.LatticeElement) << "\n"; + *OS << "Value: " << LToString(Iter.LatticeElement) << "\n"; } } } private: DataflowAnalysisResults AnalysisResults{}; - llvm::raw_ostream &OS = llvm::outs(); + MaybeUniquePtr OS = &llvm::outs(); }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 82aa8814cf..467a59d68e 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -1,6 +1,7 @@ #ifndef PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H #define PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H #include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" #include "phasar/Utils/Logger.h" @@ -9,6 +10,7 @@ #include "llvm/Support/MemoryBuffer.h" #include +#include #include #include @@ -24,12 +26,13 @@ class SourceMgrPrinter : public AnalysisPrinterBase { void onResult(Warning Warn) override { auto BufIdOpt = getSourceBufId(getFilePathFromIR(Warn.Instr)); if (BufIdOpt.has_value()) { - SrcMgr.PrintMessage(*OS, - SrcMgr.FindLocForLineAndColumn( - BufIdOpt.value(), - getLineAndColFromIR(Warn.Instr).first, - getLineAndColFromIR(Warn.Instr).second), - llvm::SourceMgr::DK_Warning, Msg); + SrcMgr.PrintMessage( + *OS, + SrcMgr.FindLocForLineAndColumn( + BufIdOpt.value(), getLineAndColFromIR(Warn.Instr).first, + getLineAndColFromIR(Warn.Instr).second), + llvm::SourceMgr::DK_Warning, + toString(Warn.AnalysisType) + " Analysis found an error"); } } @@ -52,7 +55,6 @@ class SourceMgrPrinter : public AnalysisPrinterBase { private: llvm::SourceMgr SrcMgr; llvm::StringMap FileNameIDMap; - static constexpr llvm::StringLiteral Msg = "Phasar found an error"; MaybeUniquePtr OS = &llvm::errs(); }; } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index e6f81bdd03..ee613c2116 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -19,8 +19,8 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/ExtendedTaintAnalysis/TransferEdgeFunction.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" -#include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" #include "phasar/Pointer/PointsToInfo.h" #include "phasar/Utils/DebugOutput.h" #include "phasar/Utils/Logger.h" @@ -229,7 +229,8 @@ void IDEExtendedTaintAnalysis::reportLeakIfNecessary( if (isSink(SinkCandidate, Inst)) { Leaks[Inst].insert(LeakCandidate); Warning Warn( - Inst, makeFlowFact(LeakCandidate), Top{}); + Inst, makeFlowFact(LeakCandidate), Top{}, + DataFlowAnalysisType::IDEExtendedTaintAnalysis); Printer->onResult(Warn); } } @@ -755,8 +756,9 @@ void IDEExtendedTaintAnalysis::emitTextReport( for (auto &[Inst, LeakSet] : Leaks) { for (const auto &Leak : LeakSet) { - Warning Warn(Inst, makeFlowFact(Leak), - Top{}); + Warning Warn( + Inst, makeFlowFact(Leak), Top{}, + DataFlowAnalysisType::IDEExtendedTaintAnalysis); Printer->onResult(Warn); } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index e634961926..246ae89814 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -19,6 +19,7 @@ #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/PhasarLLVM/TaintConfig/TaintConfigUtilities.h" +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" @@ -410,8 +411,9 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, CallSite](d_t Source) -> container_type { if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Warning Warn(CallSite, Source, - topElement()); + Warning Warn( + CallSite, Source, topElement(), + DataFlowAnalysisType::IFDSTaintAnalysis); Printer->onResult(Warn); } } @@ -439,8 +441,9 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Warning Warn(CallSite, Source, - topElement()); + Warning Warn( + CallSite, Source, topElement(), + DataFlowAnalysisType::IFDSTaintAnalysis); Printer->onResult(Warn); } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp index c00eae3381..49f5e5a08c 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp @@ -13,6 +13,7 @@ #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h" +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" @@ -203,8 +204,9 @@ IFDSUninitializedVariables::getNormalFlowFunction( !llvm::isa(Curr) && !llvm::isa(Curr)) { UndefValueUses[Curr].insert(Operand); - Warning Warn(Curr, Operand, - BinaryDomain::TOP); + Warning Warn( + Curr, Operand, BinaryDomain::TOP, + DataFlowAnalysisType::IFDSUninitializedVariables); Printer->onResult(Warn); } return {Source, Curr}; From 13694991c57064b26be132f5110f306151f453ff Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Tue, 6 Feb 2024 14:36:57 +0100 Subject: [PATCH 14/27] refactoring the printers --- .../phasar/DataFlow/IfdsIde/IDETabulationProblem.h | 2 +- .../{PhasarLLVM => }/Utils/AnalysisPrinterBase.h | 7 ++----- .../{PhasarLLVM => }/Utils/DefaultAnalysisPrinter.h | 11 +++++------ .../{PhasarLLVM => }/Utils/NullAnalysisPrinter.h | 4 ++-- .../{PhasarLLVM => }/Utils/OnTheFlyAnalysisPrinter.h | 6 +++--- unittests/Utils/AnalysisPrinterTest.cpp | 4 ++-- unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp | 6 ++---- unittests/Utils/SourceMgrPrinterTest.cpp | 9 ++++++--- 8 files changed, 23 insertions(+), 26 deletions(-) rename include/phasar/{PhasarLLVM => }/Utils/AnalysisPrinterBase.h (88%) rename include/phasar/{PhasarLLVM => }/Utils/DefaultAnalysisPrinter.h (77%) rename include/phasar/{PhasarLLVM => }/Utils/NullAnalysisPrinter.h (85%) rename include/phasar/{PhasarLLVM => }/Utils/OnTheFlyAnalysisPrinter.h (90%) diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index 35bd80ae56..d3c75c1aec 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -19,8 +19,8 @@ #include "phasar/DataFlow/IfdsIde/IFDSIDESolverConfig.h" #include "phasar/DataFlow/IfdsIde/InitialSeeds.h" #include "phasar/DataFlow/IfdsIde/SolverResults.h" -#include "phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h" #include "phasar/Utils/JoinLattice.h" +#include "phasar/Utils/NullAnalysisPrinter.h" #include "phasar/Utils/Printer.h" #include "phasar/Utils/Soundness.h" diff --git a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h b/include/phasar/Utils/AnalysisPrinterBase.h similarity index 88% rename from include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h rename to include/phasar/Utils/AnalysisPrinterBase.h index 2318f95e82..1a90a35f73 100644 --- a/include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h +++ b/include/phasar/Utils/AnalysisPrinterBase.h @@ -7,6 +7,7 @@ namespace psr { +// move warning to default analysis printer template struct Warning { using n_t = typename AnalysisDomainTy::n_t; using d_t = typename AnalysisDomainTy::d_t; @@ -24,15 +25,11 @@ template struct Warning { LatticeElement(std::move(Lattice)), AnalysisType(DfAnalysisType) {} }; -template struct DataflowAnalysisResults { - std::vector> Warn; -}; - template class AnalysisPrinterBase { public: virtual void onResult(Warning /*Warn*/) = 0; virtual void onInitialize() = 0; - virtual void onFinalize() const = 0; + virtual void onFinalize() = 0; AnalysisPrinterBase() = default; virtual ~AnalysisPrinterBase() = default; diff --git a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h b/include/phasar/Utils/DefaultAnalysisPrinter.h similarity index 77% rename from include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h rename to include/phasar/Utils/DefaultAnalysisPrinter.h index 4f7e236762..35ebf4e0ab 100644 --- a/include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/Utils/DefaultAnalysisPrinter.h @@ -2,8 +2,7 @@ #define PHASAR_PHASARLLVM_UTILS_DEFAULTANALYSISPRINTER_H #include "phasar/Domain/BinaryDomain.h" -#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" -#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/AnalysisPrinterBase.h" #include "phasar/Utils/MaybeUniquePtr.h" #include "phasar/Utils/Printer.h" @@ -22,12 +21,12 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(&OS) {} void onResult(Warning Warn) override { - AnalysisResults.Warn.emplace_back(std::move(Warn)); + AnalysisResults.emplace_back(std::move(Warn)); } void onInitialize() override{}; - void onFinalize() const override { - for (const auto &Iter : AnalysisResults.Warn) { + void onFinalize() override { + for (const auto &Iter : AnalysisResults) { *OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; @@ -40,7 +39,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { } private: - DataflowAnalysisResults AnalysisResults{}; + std::vector> AnalysisResults{}; MaybeUniquePtr OS = &llvm::outs(); }; diff --git a/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h b/include/phasar/Utils/NullAnalysisPrinter.h similarity index 85% rename from include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h rename to include/phasar/Utils/NullAnalysisPrinter.h index 03bf14439c..5054d0ac16 100644 --- a/include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h +++ b/include/phasar/Utils/NullAnalysisPrinter.h @@ -1,7 +1,7 @@ #ifndef PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H #define PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H -#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/Utils/AnalysisPrinterBase.h" namespace psr { @@ -15,7 +15,7 @@ class NullAnalysisPrinter final : public AnalysisPrinterBase { void onInitialize() override{}; void onResult(Warning /*War*/) override{}; - void onFinalize() const override{}; + void onFinalize() override{}; private: NullAnalysisPrinter() = default; diff --git a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h similarity index 90% rename from include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h rename to include/phasar/Utils/OnTheFlyAnalysisPrinter.h index 729d78269f..1bcd5471d8 100644 --- a/include/phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h @@ -2,7 +2,7 @@ #define PHASAR_PHASARLLVM_UTILS_ONTHEFLYANALYSISPRINTER_H #include "phasar/Domain/BinaryDomain.h" -#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/Utils/AnalysisPrinterBase.h" #include "phasar/Utils/IO.h" #include "phasar/Utils/MaybeUniquePtr.h" #include "phasar/Utils/Printer.h" @@ -38,9 +38,9 @@ class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { } } - void onFinalize() const override{}; + void onFinalize() override{}; - bool isValid() { return OS != nullptr; } + [[nodiscard]] bool isValid() const noexcept { return OS != nullptr; } private: MaybeUniquePtr OS = nullptr; diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index a0941825e2..a077164545 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -7,9 +7,9 @@ #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TaintConfig/TaintConfigData.h" -#include "phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/DefaultAnalysisPrinter.h" #include "llvm/ADT/DenseMap.h" @@ -47,7 +47,7 @@ class GroundTruthCollector findAndRemove(FoundLeak, GroundTruth); } - void onFinalize() const override { EXPECT_TRUE(GroundTruth.empty()); } + void onFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } private: llvm::DenseMap> GroundTruth{}; diff --git a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp index 45baf161de..141acf9730 100644 --- a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp +++ b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp @@ -1,12 +1,10 @@ -#include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" +#include "phasar/Utils/OnTheFlyAnalysisPrinter.h" #include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" -#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" -#include "phasar/PhasarLLVM/Utils/SourceMgrPrinter.h" #include "llvm/ADT/DenseMap.h" @@ -45,7 +43,7 @@ class GroundTruthCollector findAndRemove(FoundLeak, GroundTruth); } - void onFinalize() const override { EXPECT_TRUE(GroundTruth.empty()); } + void onFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } private: llvm::DenseMap> GroundTruth{}; diff --git a/unittests/Utils/SourceMgrPrinterTest.cpp b/unittests/Utils/SourceMgrPrinterTest.cpp index 985aff708f..7fedc19468 100644 --- a/unittests/Utils/SourceMgrPrinterTest.cpp +++ b/unittests/Utils/SourceMgrPrinterTest.cpp @@ -3,9 +3,11 @@ #include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h" +#include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" -#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" +#include "phasar/Utils/AnalysisPrinterBase.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -22,7 +24,8 @@ class GroundTruthCollector public: // constructor init Groundtruth in each fixture GroundTruthCollector(std::set &GroundTruth) - : SourceMgrPrinter(OS), + : SourceMgrPrinter( + [](DataFlowAnalysisType) { return ""; }, OS), GroundTruth(GroundTruth), OS(Str){}; std::string findSubString(const std::string &String) { @@ -53,7 +56,7 @@ class GroundTruthCollector findAndRemove(OS.str()); } - void onFinalize() const override { EXPECT_TRUE(GroundTruth.empty()); } + void onFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } private: std::set GroundTruth{}; From 29e7b8ac34e05199e2ae50f84a29555ccece483d Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Fri, 9 Feb 2024 14:10:52 +0100 Subject: [PATCH 15/27] adding TODOs --- .../PhasarLLVM/Utils/SourceMgrPrinter.h | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 467a59d68e..6144086ad7 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -1,41 +1,51 @@ #ifndef PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H #define PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H -#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h" #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" -#include "phasar/PhasarLLVM/Utils/OnTheFlyAnalysisPrinter.h" +#include "phasar/Utils/AnalysisPrinterBase.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/MaybeUniquePtr.h" +#include "llvm/ADT/FunctionExtras.h" #include "llvm/Support/MemoryBuffer.h" #include #include #include -#include +#include // quoting style namespace psr { template class SourceMgrPrinter : public AnalysisPrinterBase { public: - SourceMgrPrinter() = default; - SourceMgrPrinter(llvm::raw_ostream &OS) : OS(&OS){}; + SourceMgrPrinter( + llvm::unique_function &&PrintMessage, + llvm::raw_ostream &OS = llvm::errs()) + : GetPrintMessage(std::move(PrintMessage)), OS(&OS) {} void onInitialize() override {} - void onFinalize() const override{}; + void onFinalize() override {} void onResult(Warning Warn) override { auto BufIdOpt = getSourceBufId(getFilePathFromIR(Warn.Instr)); if (BufIdOpt.has_value()) { - SrcMgr.PrintMessage( - *OS, - SrcMgr.FindLocForLineAndColumn( - BufIdOpt.value(), getLineAndColFromIR(Warn.Instr).first, - getLineAndColFromIR(Warn.Instr).second), - llvm::SourceMgr::DK_Warning, - toString(Warn.AnalysisType) + " Analysis found an error"); + /// TODO: getLineAndColFromIR call only once + /// TODO:Configuration options for warning or error + SrcMgr.PrintMessage(*OS, + SrcMgr.FindLocForLineAndColumn( + BufIdOpt.value(), + getLineAndColFromIR(Warn.Instr).first, + getLineAndColFromIR(Warn.Instr).second), + llvm::SourceMgr::DK_Warning, + + GetPrintMessage(Warn.AnalysisType)); } } + /// TODO: use non-virtual function to call virtual function with default + /// parameters + + /// TODO: templace magic - #include "memory_resource" + + /// TODO: move this to cpp file and refactor the imports std::optional getSourceBufId(llvm::StringRef FileName) { if (auto It = FileNameIDMap.find(FileName); It != FileNameIDMap.end()) { return It->second; @@ -53,8 +63,9 @@ class SourceMgrPrinter : public AnalysisPrinterBase { } private: - llvm::SourceMgr SrcMgr; - llvm::StringMap FileNameIDMap; + llvm::SourceMgr SrcMgr{}; + llvm::StringMap FileNameIDMap{}; + llvm::unique_function GetPrintMessage; MaybeUniquePtr OS = &llvm::errs(); }; } // namespace psr From 6741866b111371328ad1c70f29fe7a26b837cc4d Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Fri, 9 Feb 2024 14:17:37 +0100 Subject: [PATCH 16/27] more TODOs --- .../PhasarLLVM/Utils/SourceMgrPrinter.h | 22 +++++++------------ include/phasar/Utils/AnalysisPrinterBase.h | 5 ++++- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 6144086ad7..85fe685525 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -12,7 +12,7 @@ #include #include #include -#include // quoting style +#include /// TODO: quoting style namespace psr { template @@ -29,22 +29,16 @@ class SourceMgrPrinter : public AnalysisPrinterBase { auto BufIdOpt = getSourceBufId(getFilePathFromIR(Warn.Instr)); if (BufIdOpt.has_value()) { /// TODO: getLineAndColFromIR call only once - /// TODO:Configuration options for warning or error - SrcMgr.PrintMessage(*OS, - SrcMgr.FindLocForLineAndColumn( - BufIdOpt.value(), - getLineAndColFromIR(Warn.Instr).first, - getLineAndColFromIR(Warn.Instr).second), - llvm::SourceMgr::DK_Warning, - - GetPrintMessage(Warn.AnalysisType)); + /// TODO: Configuration options for warning or error + SrcMgr.PrintMessage( + *OS, + SrcMgr.FindLocForLineAndColumn( + BufIdOpt.value(), getLineAndColFromIR(Warn.Instr).first, + getLineAndColFromIR(Warn.Instr).second), + llvm::SourceMgr::DK_Warning, GetPrintMessage(Warn.AnalysisType)); } } - /// TODO: use non-virtual function to call virtual function with default - /// parameters + - /// TODO: templace magic - #include "memory_resource" - /// TODO: move this to cpp file and refactor the imports std::optional getSourceBufId(llvm::StringRef FileName) { if (auto It = FileNameIDMap.find(FileName); It != FileNameIDMap.end()) { diff --git a/include/phasar/Utils/AnalysisPrinterBase.h b/include/phasar/Utils/AnalysisPrinterBase.h index 1a90a35f73..101440614f 100644 --- a/include/phasar/Utils/AnalysisPrinterBase.h +++ b/include/phasar/Utils/AnalysisPrinterBase.h @@ -7,7 +7,7 @@ namespace psr { -// move warning to default analysis printer +/// TODO: move warning to default analysis printer template struct Warning { using n_t = typename AnalysisDomainTy::n_t; using d_t = typename AnalysisDomainTy::d_t; @@ -27,6 +27,9 @@ template struct Warning { template class AnalysisPrinterBase { public: + /// TODO: use non-virtual function to call virtual function with default + /// parameters + + /// TODO: templace magic - #include "memory_resource" virtual void onResult(Warning /*Warn*/) = 0; virtual void onInitialize() = 0; virtual void onFinalize() = 0; From 1cc8a2629305d9b783ceed156637d861e034ca91 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Mon, 12 Feb 2024 13:29:37 +0100 Subject: [PATCH 17/27] Refactor AnalysisPrinter part1 --- .../PhasarLLVM/Utils/SourceMgrPrinter.h | 30 +++++-------------- lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp | 25 ++++++++++++++++ 2 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 85fe685525..2314411f49 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -15,6 +15,9 @@ #include /// TODO: quoting style namespace psr { + +std::optional getSourceBufId(llvm::StringRef FileName); + template class SourceMgrPrinter : public AnalysisPrinterBase { public: @@ -28,39 +31,22 @@ class SourceMgrPrinter : public AnalysisPrinterBase { void onResult(Warning Warn) override { auto BufIdOpt = getSourceBufId(getFilePathFromIR(Warn.Instr)); if (BufIdOpt.has_value()) { - /// TODO: getLineAndColFromIR call only once + std::pair LineAndCol = + getLineAndColFromIR(Warn.Instr); /// TODO: Configuration options for warning or error SrcMgr.PrintMessage( *OS, - SrcMgr.FindLocForLineAndColumn( - BufIdOpt.value(), getLineAndColFromIR(Warn.Instr).first, - getLineAndColFromIR(Warn.Instr).second), + SrcMgr.FindLocForLineAndColumn(BufIdOpt.value(), LineAndCol.first, + LineAndCol.second), llvm::SourceMgr::DK_Warning, GetPrintMessage(Warn.AnalysisType)); } } - /// TODO: move this to cpp file and refactor the imports - std::optional getSourceBufId(llvm::StringRef FileName) { - if (auto It = FileNameIDMap.find(FileName); It != FileNameIDMap.end()) { - return It->second; - } - - auto Buf = llvm::MemoryBuffer::getFile(FileName, true); - if (!Buf) { - PHASAR_LOG_LEVEL(WARNING, "File not accessible: " << FileName); - return std::nullopt; - } - - auto Id = SrcMgr.AddNewSourceBuffer(std::move(Buf.get()), llvm::SMLoc{}); - FileNameIDMap.try_emplace(FileName, Id); - return Id; - } - private: llvm::SourceMgr SrcMgr{}; - llvm::StringMap FileNameIDMap{}; llvm::unique_function GetPrintMessage; MaybeUniquePtr OS = &llvm::errs(); }; + } // namespace psr #endif diff --git a/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp b/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp new file mode 100644 index 0000000000..45b0cf4a8f --- /dev/null +++ b/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp @@ -0,0 +1,25 @@ +#include "phasar/PhasarLLVM/Utils/SourceMgrPrinter.h" + +#include + +namespace psr { + +llvm::StringMap FileNameIDMap{}; +llvm::SourceMgr SrcMgr{}; + +std::optional getSourceBufId(llvm::StringRef FileName) { + if (auto It = FileNameIDMap.find(FileName); It != FileNameIDMap.end()) { + return It->second; + } + + auto Buf = llvm::MemoryBuffer::getFile(FileName, true); + if (!Buf) { + PHASAR_LOG_LEVEL(WARNING, "File not accessible: " << FileName); + return std::nullopt; + } + + auto Id = SrcMgr.AddNewSourceBuffer(std::move(Buf.get()), llvm::SMLoc{}); + FileNameIDMap.try_emplace(FileName, Id); + return Id; +} +} // namespace psr From ca7565bd0bcd8efcad3792413fff001ffda46843 Mon Sep 17 00:00:00 2001 From: SanthoshMohan Date: Mon, 12 Feb 2024 17:57:31 +0100 Subject: [PATCH 18/27] Refactor AnalysisPrinter part2 --- .../IfdsIde/Problems/IDETypeStateAnalysis.h | 12 +++----- .../PhasarLLVM/Utils/SourceMgrPrinter.h | 28 +++++++++++-------- include/phasar/Utils/AnalysisPrinterBase.h | 19 ++----------- include/phasar/Utils/DefaultAnalysisPrinter.h | 24 ++++++++++++++-- include/phasar/Utils/NullAnalysisPrinter.h | 7 ++++- .../phasar/Utils/OnTheFlyAnalysisPrinter.h | 17 ++++++----- .../Problems/IDEExtendedTaintAnalysis.cpp | 12 +++----- .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 12 +++----- .../Problems/IFDSUninitializedVariables.cpp | 6 ++-- lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp | 9 ++---- unittests/Utils/AnalysisPrinterTest.cpp | 12 ++++++-- .../Utils/OnTheFlyAnalysisPrinterTest.cpp | 16 +++++++---- unittests/Utils/SourceMgrPrinterTest.cpp | 16 +++++++---- 13 files changed, 105 insertions(+), 85 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index 559620dc62..ab579bbef1 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -530,11 +530,9 @@ class IDETypeStateAnalysis if (const auto *Alloca = llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { - Warning> - Warn(&I, Res.first, TSD->error(), - DataFlowAnalysisType::None); // ERROR STATE DETECTED - this->Printer->onResult(Warn); + this->Printer->onResult(&I, Res.first, TSD->error(), + DataFlowAnalysisType::None); } } } @@ -543,11 +541,9 @@ class IDETypeStateAnalysis if (const auto *Alloca = llvm::dyn_cast(Res.first)) { if (Res.second == TSD->error()) { - Warning> - Warn(&I, Res.first, TSD->error(), - DataFlowAnalysisType::None); // ERROR STATE DETECTED - this->Printer->onResult(Warn); + this->Printer->onResult(&I, Res.first, TSD->error(), + DataFlowAnalysisType::None); } } } diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 2314411f49..4848b43a8b 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -7,19 +7,22 @@ #include "phasar/Utils/MaybeUniquePtr.h" #include "llvm/ADT/FunctionExtras.h" -#include "llvm/Support/MemoryBuffer.h" - -#include -#include -#include -#include /// TODO: quoting style +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" namespace psr { -std::optional getSourceBufId(llvm::StringRef FileName); +std::optional getSourceBufId(llvm::StringRef FileName, + llvm::StringMap &FileNameIDMap, + llvm::SourceMgr &SrcMgr); template class SourceMgrPrinter : public AnalysisPrinterBase { + using n_t = typename AnalysisDomainTy::n_t; + using d_t = typename AnalysisDomainTy::d_t; + using l_t = typename AnalysisDomainTy::l_t; + public: SourceMgrPrinter( llvm::unique_function &&PrintMessage, @@ -28,21 +31,24 @@ class SourceMgrPrinter : public AnalysisPrinterBase { void onInitialize() override {} void onFinalize() override {} - void onResult(Warning Warn) override { - auto BufIdOpt = getSourceBufId(getFilePathFromIR(Warn.Instr)); + void onResult(n_t Instr, d_t /*DfFact*/, l_t /*Lattice*/, + DataFlowAnalysisType AnalysisType) override { + auto BufIdOpt = + getSourceBufId(getFilePathFromIR(Instr), FileNameIDMap, SrcMgr); if (BufIdOpt.has_value()) { std::pair LineAndCol = - getLineAndColFromIR(Warn.Instr); + getLineAndColFromIR(Instr); /// TODO: Configuration options for warning or error SrcMgr.PrintMessage( *OS, SrcMgr.FindLocForLineAndColumn(BufIdOpt.value(), LineAndCol.first, LineAndCol.second), - llvm::SourceMgr::DK_Warning, GetPrintMessage(Warn.AnalysisType)); + llvm::SourceMgr::DK_Warning, GetPrintMessage(AnalysisType)); } } private: + llvm::StringMap FileNameIDMap{}; llvm::SourceMgr SrcMgr{}; llvm::unique_function GetPrintMessage; MaybeUniquePtr OS = &llvm::errs(); diff --git a/include/phasar/Utils/AnalysisPrinterBase.h b/include/phasar/Utils/AnalysisPrinterBase.h index 101440614f..a2eda5d99f 100644 --- a/include/phasar/Utils/AnalysisPrinterBase.h +++ b/include/phasar/Utils/AnalysisPrinterBase.h @@ -7,30 +7,17 @@ namespace psr { -/// TODO: move warning to default analysis printer -template struct Warning { +template class AnalysisPrinterBase { using n_t = typename AnalysisDomainTy::n_t; using d_t = typename AnalysisDomainTy::d_t; using l_t = typename AnalysisDomainTy::l_t; - n_t Instr; - d_t Fact; - l_t LatticeElement; - DataFlowAnalysisType AnalysisType; - - // Constructor - Warning(n_t Inst, d_t DfFact, l_t Lattice, - DataFlowAnalysisType DfAnalysisType) - : Instr(std::move(Inst)), Fact(std::move(DfFact)), - LatticeElement(std::move(Lattice)), AnalysisType(DfAnalysisType) {} -}; - -template class AnalysisPrinterBase { public: /// TODO: use non-virtual function to call virtual function with default /// parameters + /// TODO: templace magic - #include "memory_resource" - virtual void onResult(Warning /*Warn*/) = 0; + virtual void onResult(n_t /*Instr*/, d_t /*DfFact*/, l_t /*LatticeElement*/, + DataFlowAnalysisType /*AnalysisType*/) = 0; virtual void onInitialize() = 0; virtual void onFinalize() = 0; diff --git a/include/phasar/Utils/DefaultAnalysisPrinter.h b/include/phasar/Utils/DefaultAnalysisPrinter.h index 35ebf4e0ab..da601e7d0b 100644 --- a/include/phasar/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/Utils/DefaultAnalysisPrinter.h @@ -12,16 +12,36 @@ namespace psr { +template struct Warning { + using n_t = typename AnalysisDomainTy::n_t; + using d_t = typename AnalysisDomainTy::d_t; + using l_t = typename AnalysisDomainTy::l_t; + + n_t Instr; + d_t Fact; + l_t LatticeElement; + DataFlowAnalysisType AnalysisType; + + // Constructor + Warning(n_t Inst, d_t DfFact, l_t Lattice, + DataFlowAnalysisType DfAnalysisType) + : Instr(std::move(Inst)), Fact(std::move(DfFact)), + LatticeElement(std::move(Lattice)), AnalysisType(DfAnalysisType) {} +}; + template class DefaultAnalysisPrinter : public AnalysisPrinterBase { + using n_t = typename AnalysisDomainTy::n_t; + using d_t = typename AnalysisDomainTy::d_t; using l_t = typename AnalysisDomainTy::l_t; public: ~DefaultAnalysisPrinter() override = default; DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(&OS) {} - void onResult(Warning Warn) override { - AnalysisResults.emplace_back(std::move(Warn)); + void onResult(n_t Instr, d_t DfFact, l_t Lattice, + DataFlowAnalysisType AnalysisType) override { + AnalysisResults.emplace_back(Instr, DfFact, Lattice, AnalysisType); } void onInitialize() override{}; diff --git a/include/phasar/Utils/NullAnalysisPrinter.h b/include/phasar/Utils/NullAnalysisPrinter.h index 5054d0ac16..7e07fd2711 100644 --- a/include/phasar/Utils/NullAnalysisPrinter.h +++ b/include/phasar/Utils/NullAnalysisPrinter.h @@ -7,6 +7,10 @@ namespace psr { template class NullAnalysisPrinter final : public AnalysisPrinterBase { + using n_t = typename AnalysisDomainTy::n_t; + using d_t = typename AnalysisDomainTy::d_t; + using l_t = typename AnalysisDomainTy::l_t; + public: static NullAnalysisPrinter *getInstance() { static auto Instance = NullAnalysisPrinter(); @@ -14,7 +18,8 @@ class NullAnalysisPrinter final : public AnalysisPrinterBase { } void onInitialize() override{}; - void onResult(Warning /*War*/) override{}; + void onResult(n_t /*Instr*/, d_t /*DfFact*/, l_t /*Lattice*/, + DataFlowAnalysisType /*AnalysisType*/) override{}; void onFinalize() override{}; private: diff --git a/include/phasar/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h index 1bcd5471d8..72400bb079 100644 --- a/include/phasar/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h @@ -7,14 +7,16 @@ #include "phasar/Utils/MaybeUniquePtr.h" #include "phasar/Utils/Printer.h" -#include +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" -#include -#include +#include namespace psr { template class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { + using n_t = typename AnalysisDomainTy::n_t; + using d_t = typename AnalysisDomainTy::d_t; using l_t = typename AnalysisDomainTy::l_t; public: @@ -29,12 +31,13 @@ class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { ~OnTheFlyAnalysisPrinter() = default; void onInitialize() override{}; - void onResult(Warning Warn) override { + void onResult(n_t Instr, d_t DfFact, l_t LatticeElement, + DataFlowAnalysisType /*AnalysisType*/) override { assert(isValid()); - *OS << "\nAt IR statement: " << NToString(Warn.Instr) << "\n"; - *OS << "\tFact: " << DToString(Warn.Fact) << "\n"; + *OS << "\nAt IR statement: " << NToString(Instr) << "\n"; + *OS << "\tFact: " << DToString(DfFact) << "\n"; if constexpr (std::is_same_v) { - *OS << "Value: " << LToString(Warn.LatticeElement) << "\n"; + *OS << "Value: " << LToString(LatticeElement) << "\n"; } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index ee613c2116..f5b799d906 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -228,10 +228,8 @@ void IDEExtendedTaintAnalysis::reportLeakIfNecessary( const llvm::Value *LeakCandidate) { if (isSink(SinkCandidate, Inst)) { Leaks[Inst].insert(LeakCandidate); - Warning Warn( - Inst, makeFlowFact(LeakCandidate), Top{}, - DataFlowAnalysisType::IDEExtendedTaintAnalysis); - Printer->onResult(Warn); + Printer->onResult(Inst, makeFlowFact(LeakCandidate), Top{}, + DataFlowAnalysisType::IDEExtendedTaintAnalysis); } } @@ -756,10 +754,8 @@ void IDEExtendedTaintAnalysis::emitTextReport( for (auto &[Inst, LeakSet] : Leaks) { for (const auto &Leak : LeakSet) { - Warning Warn( - Inst, makeFlowFact(Leak), Top{}, - DataFlowAnalysisType::IDEExtendedTaintAnalysis); - Printer->onResult(Warn); + Printer->onResult(Inst, makeFlowFact(Leak), Top{}, + DataFlowAnalysisType::IDEExtendedTaintAnalysis); } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index 246ae89814..a8c37bde46 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -411,10 +411,8 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, CallSite](d_t Source) -> container_type { if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Warning Warn( - CallSite, Source, topElement(), - DataFlowAnalysisType::IFDSTaintAnalysis); - Printer->onResult(Warn); + Printer->onResult(CallSite, Source, topElement(), + DataFlowAnalysisType::IFDSTaintAnalysis); } } @@ -441,10 +439,8 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Warning Warn( - CallSite, Source, topElement(), - DataFlowAnalysisType::IFDSTaintAnalysis); - Printer->onResult(Warn); + Printer->onResult(CallSite, Source, topElement(), + DataFlowAnalysisType::IFDSTaintAnalysis); } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp index 49f5e5a08c..0640f4e8a4 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp @@ -204,10 +204,8 @@ IFDSUninitializedVariables::getNormalFlowFunction( !llvm::isa(Curr) && !llvm::isa(Curr)) { UndefValueUses[Curr].insert(Operand); - Warning Warn( - Curr, Operand, BinaryDomain::TOP, - DataFlowAnalysisType::IFDSUninitializedVariables); - Printer->onResult(Warn); + Printer->onResult(Curr, Operand, BinaryDomain::TOP, + DataFlowAnalysisType::IFDSUninitializedVariables); } return {Source, Curr}; } diff --git a/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp b/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp index 45b0cf4a8f..b2205670fa 100644 --- a/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp +++ b/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp @@ -1,13 +1,10 @@ #include "phasar/PhasarLLVM/Utils/SourceMgrPrinter.h" -#include - namespace psr { -llvm::StringMap FileNameIDMap{}; -llvm::SourceMgr SrcMgr{}; - -std::optional getSourceBufId(llvm::StringRef FileName) { +std::optional getSourceBufId(llvm::StringRef FileName, + llvm::StringMap &FileNameIDMap, + llvm::SourceMgr &SrcMgr) { if (auto It = FileNameIDMap.find(FileName); It != FileNameIDMap.end()) { return It->second; } diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index a077164545..976d272176 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -22,6 +22,11 @@ using CallBackPairTy = std::pair::config_callback_t, // Use template to variate between Typesate and Taint analysis class GroundTruthCollector : public DefaultAnalysisPrinter { + + using n_t = IDEExtendedTaintAnalysisDomain::n_t; + using d_t = IDEExtendedTaintAnalysisDomain::d_t; + using l_t = IDEExtendedTaintAnalysisDomain::l_t; + public: // constructor init Groundtruth in each fixture GroundTruthCollector(llvm::DenseMap> &GroundTruth) @@ -38,11 +43,12 @@ class GroundTruthCollector } } - void onResult(Warning Warn) override { + void onResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, + DataFlowAnalysisType /*AnalysisType*/) override { llvm::DenseMap> FoundLeak; - int SinkId = stoi(getMetaDataID(Warn.Instr)); + int SinkId = stoi(getMetaDataID(Instr)); std::set LeakedValueIds; - LeakedValueIds.insert(getMetaDataID((Warn.Fact)->base())); + LeakedValueIds.insert(getMetaDataID((DfFact)->base())); FoundLeak.try_emplace(SinkId, LeakedValueIds); findAndRemove(FoundLeak, GroundTruth); } diff --git a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp index 141acf9730..5632c614cc 100644 --- a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp +++ b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp @@ -7,17 +7,20 @@ #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include -#include - using namespace psr; class GroundTruthCollector : public OnTheFlyAnalysisPrinter { + using n_t = LLVMIFDSAnalysisDomainDefault::n_t; + using d_t = LLVMIFDSAnalysisDomainDefault::d_t; + using l_t = LLVMIFDSAnalysisDomainDefault::l_t; + public: // constructor init Groundtruth in each fixture GroundTruthCollector(llvm::DenseMap> &GroundTruth) @@ -34,11 +37,12 @@ class GroundTruthCollector } } - void onResult(Warning Warn) override { + void onResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, + DataFlowAnalysisType /*AnalysisType*/) override { llvm::DenseMap> FoundLeak; - int SinkId = stoi(getMetaDataID(Warn.Instr)); + int SinkId = stoi(getMetaDataID(Instr)); std::set LeakedValueIds; - LeakedValueIds.insert(getMetaDataID((Warn.Fact))); + LeakedValueIds.insert(getMetaDataID((DfFact))); FoundLeak.try_emplace(SinkId, LeakedValueIds); findAndRemove(FoundLeak, GroundTruth); } diff --git a/unittests/Utils/SourceMgrPrinterTest.cpp b/unittests/Utils/SourceMgrPrinterTest.cpp index 7fedc19468..1592e3a05c 100644 --- a/unittests/Utils/SourceMgrPrinterTest.cpp +++ b/unittests/Utils/SourceMgrPrinterTest.cpp @@ -9,18 +9,22 @@ #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/Utils/AnalysisPrinterBase.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + #include "TestConfig.h" #include "gtest/gtest.h" #include -#include -#include - using namespace psr; class GroundTruthCollector : public SourceMgrPrinter { + using n_t = LLVMIFDSAnalysisDomainDefault::n_t; + using d_t = LLVMIFDSAnalysisDomainDefault::d_t; + using l_t = LLVMIFDSAnalysisDomainDefault::l_t; + public: // constructor init Groundtruth in each fixture GroundTruthCollector(std::set &GroundTruth) @@ -51,8 +55,10 @@ class GroundTruthCollector GroundTruth.erase(SubString); } - void onResult(Warning Warn) override { - SourceMgrPrinter::onResult(Warn); + void onResult(n_t Instr, d_t DfFact, l_t LatticeElement, + DataFlowAnalysisType AnalysisType) override { + SourceMgrPrinter::onResult( + Instr, DfFact, LatticeElement, AnalysisType); findAndRemove(OS.str()); } From 54af9e6f39e91c8df121712c6c88d7d1f154ea0c Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Wed, 14 Feb 2024 12:13:02 +0100 Subject: [PATCH 19/27] dev: update AnalysisPrinterBase, integrate and fix tests --- .../PhasarLLVM/Utils/SourceMgrPrinter.h | 8 ++-- include/phasar/Utils/AnalysisPrinterBase.h | 33 +++++++++++++---- include/phasar/Utils/DefaultAnalysisPrinter.h | 9 ++--- include/phasar/Utils/NullAnalysisPrinter.h | 8 ++-- .../phasar/Utils/OnTheFlyAnalysisPrinter.h | 13 +++---- .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 4 +- .../Problems/IFDSUninitializedVariables.cpp | 2 +- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 2 +- unittests/Utils/AnalysisPrinterTest.cpp | 8 ++-- .../Utils/OnTheFlyAnalysisPrinterTest.cpp | 8 ++-- unittests/Utils/SourceMgrPrinterTest.cpp | 37 ++++--------------- 11 files changed, 61 insertions(+), 71 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 4848b43a8b..5cb4768f76 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -29,10 +29,9 @@ class SourceMgrPrinter : public AnalysisPrinterBase { llvm::raw_ostream &OS = llvm::errs()) : GetPrintMessage(std::move(PrintMessage)), OS(&OS) {} - void onInitialize() override {} - void onFinalize() override {} - void onResult(n_t Instr, d_t /*DfFact*/, l_t /*Lattice*/, - DataFlowAnalysisType AnalysisType) override { +private: + void doOnResult(n_t Instr, d_t /*DfFact*/, l_t /*Lattice*/, + DataFlowAnalysisType AnalysisType) override { auto BufIdOpt = getSourceBufId(getFilePathFromIR(Instr), FileNameIDMap, SrcMgr); if (BufIdOpt.has_value()) { @@ -47,7 +46,6 @@ class SourceMgrPrinter : public AnalysisPrinterBase { } } -private: llvm::StringMap FileNameIDMap{}; llvm::SourceMgr SrcMgr{}; llvm::unique_function GetPrintMessage; diff --git a/include/phasar/Utils/AnalysisPrinterBase.h b/include/phasar/Utils/AnalysisPrinterBase.h index a2eda5d99f..a1ca6aee39 100644 --- a/include/phasar/Utils/AnalysisPrinterBase.h +++ b/include/phasar/Utils/AnalysisPrinterBase.h @@ -1,10 +1,13 @@ #ifndef PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H #define PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H +#include "phasar/Domain/BinaryDomain.h" #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "llvm/Support/raw_ostream.h" +#include + namespace psr { template class AnalysisPrinterBase { @@ -13,13 +16,22 @@ template class AnalysisPrinterBase { using l_t = typename AnalysisDomainTy::l_t; public: - /// TODO: use non-virtual function to call virtual function with default - /// parameters + - /// TODO: templace magic - #include "memory_resource" - virtual void onResult(n_t /*Instr*/, d_t /*DfFact*/, l_t /*LatticeElement*/, - DataFlowAnalysisType /*AnalysisType*/) = 0; - virtual void onInitialize() = 0; - virtual void onFinalize() = 0; + template , psr::BinaryDomain>>> + void onResult(n_t Instr, d_t DfFact, l_t LatticeElement, + DataFlowAnalysisType AnalysisType) { + doOnResult(Instr, DfFact, LatticeElement, AnalysisType); + } + + template , psr::BinaryDomain>>> + void onResult(n_t Instr, d_t DfFact, DataFlowAnalysisType AnalysisType) { + doOnResult(Instr, DfFact, psr::BinaryDomain::BOTTOM, AnalysisType); + } + + void onInitialize() { doOnInitialize(); } + + void onFinalize() { doOnFinalize(); } AnalysisPrinterBase() = default; virtual ~AnalysisPrinterBase() = default; @@ -28,6 +40,13 @@ template class AnalysisPrinterBase { AnalysisPrinterBase(AnalysisPrinterBase &&) = delete; AnalysisPrinterBase &operator=(AnalysisPrinterBase &&) = delete; + +private: + virtual void doOnResult(n_t /*Instr*/, d_t /*DfFact*/, l_t /*LatticeElement*/, + DataFlowAnalysisType /*AnalysisType*/) = 0; + + virtual void doOnInitialize() {} + virtual void doOnFinalize() {} }; } // namespace psr diff --git a/include/phasar/Utils/DefaultAnalysisPrinter.h b/include/phasar/Utils/DefaultAnalysisPrinter.h index da601e7d0b..fcf4aeb13c 100644 --- a/include/phasar/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/Utils/DefaultAnalysisPrinter.h @@ -39,13 +39,13 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { ~DefaultAnalysisPrinter() override = default; DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(&OS) {} - void onResult(n_t Instr, d_t DfFact, l_t Lattice, - DataFlowAnalysisType AnalysisType) override { +private: + void doOnResult(n_t Instr, d_t DfFact, l_t Lattice, + DataFlowAnalysisType AnalysisType) override { AnalysisResults.emplace_back(Instr, DfFact, Lattice, AnalysisType); } - void onInitialize() override{}; - void onFinalize() override { + void doOnFinalize() override { for (const auto &Iter : AnalysisResults) { *OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n"; @@ -58,7 +58,6 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { } } -private: std::vector> AnalysisResults{}; MaybeUniquePtr OS = &llvm::outs(); }; diff --git a/include/phasar/Utils/NullAnalysisPrinter.h b/include/phasar/Utils/NullAnalysisPrinter.h index 7e07fd2711..8527cc3c8d 100644 --- a/include/phasar/Utils/NullAnalysisPrinter.h +++ b/include/phasar/Utils/NullAnalysisPrinter.h @@ -17,12 +17,10 @@ class NullAnalysisPrinter final : public AnalysisPrinterBase { return &Instance; } - void onInitialize() override{}; - void onResult(n_t /*Instr*/, d_t /*DfFact*/, l_t /*Lattice*/, - DataFlowAnalysisType /*AnalysisType*/) override{}; - void onFinalize() override{}; - private: + void doOnResult(n_t /*Instr*/, d_t /*DfFact*/, l_t /*Lattice*/, + DataFlowAnalysisType /*AnalysisType*/) override{}; + NullAnalysisPrinter() = default; }; diff --git a/include/phasar/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h index 72400bb079..08be84dda7 100644 --- a/include/phasar/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h @@ -30,9 +30,11 @@ class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { OnTheFlyAnalysisPrinter() = default; ~OnTheFlyAnalysisPrinter() = default; - void onInitialize() override{}; - void onResult(n_t Instr, d_t DfFact, l_t LatticeElement, - DataFlowAnalysisType /*AnalysisType*/) override { + [[nodiscard]] bool isValid() const noexcept { return OS != nullptr; } + +private: + void doOnResult(n_t Instr, d_t DfFact, l_t LatticeElement, + DataFlowAnalysisType /*AnalysisType*/) override { assert(isValid()); *OS << "\nAt IR statement: " << NToString(Instr) << "\n"; *OS << "\tFact: " << DToString(DfFact) << "\n"; @@ -41,11 +43,6 @@ class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { } } - void onFinalize() override{}; - - [[nodiscard]] bool isValid() const noexcept { return OS != nullptr; } - -private: MaybeUniquePtr OS = nullptr; }; } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index a8c37bde46..a39fbee4b9 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -411,7 +411,7 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, CallSite](d_t Source) -> container_type { if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Printer->onResult(CallSite, Source, topElement(), + Printer->onResult(CallSite, Source, DataFlowAnalysisType::IFDSTaintAnalysis); } } @@ -439,7 +439,7 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, if (Leak.count(Source)) { if (Leaks[CallSite].insert(Source).second) { - Printer->onResult(CallSite, Source, topElement(), + Printer->onResult(CallSite, Source, DataFlowAnalysisType::IFDSTaintAnalysis); } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp index 0640f4e8a4..68e360b35f 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp @@ -204,7 +204,7 @@ IFDSUninitializedVariables::getNormalFlowFunction( !llvm::isa(Curr) && !llvm::isa(Curr)) { UndefValueUses[Curr].insert(Operand); - Printer->onResult(Curr, Operand, BinaryDomain::TOP, + Printer->onResult(Curr, Operand, DataFlowAnalysisType::IFDSUninitializedVariables); } return {Source, Curr}; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 806cb58e2c..4862f12743 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -208,7 +208,7 @@ TEST_F(IDETaintAnalysisTest, XTaint09_1) { TEST_F(IDETaintAnalysisTest, XTaint09) { map> Gt; - Gt[34] = {"33"}; + Gt[25] = {"24"}; doAnalysis({PathToLLFiles + "xtaint09_cpp.ll"}, Gt, std::monostate{}); } diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index 976d272176..34a110d537 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -43,8 +43,9 @@ class GroundTruthCollector } } - void onResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, - DataFlowAnalysisType /*AnalysisType*/) override { +private: + void doOnResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, + DataFlowAnalysisType /*AnalysisType*/) override { llvm::DenseMap> FoundLeak; int SinkId = stoi(getMetaDataID(Instr)); std::set LeakedValueIds; @@ -53,9 +54,8 @@ class GroundTruthCollector findAndRemove(FoundLeak, GroundTruth); } - void onFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } + void doOnFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } -private: llvm::DenseMap> GroundTruth{}; }; diff --git a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp index 5632c614cc..51d793ec11 100644 --- a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp +++ b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp @@ -37,8 +37,9 @@ class GroundTruthCollector } } - void onResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, - DataFlowAnalysisType /*AnalysisType*/) override { +private: + void doOnResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, + DataFlowAnalysisType /*AnalysisType*/) override { llvm::DenseMap> FoundLeak; int SinkId = stoi(getMetaDataID(Instr)); std::set LeakedValueIds; @@ -47,9 +48,8 @@ class GroundTruthCollector findAndRemove(FoundLeak, GroundTruth); } - void onFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } + void doOnFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } -private: llvm::DenseMap> GroundTruth{}; }; diff --git a/unittests/Utils/SourceMgrPrinterTest.cpp b/unittests/Utils/SourceMgrPrinterTest.cpp index 1592e3a05c..8fda921828 100644 --- a/unittests/Utils/SourceMgrPrinterTest.cpp +++ b/unittests/Utils/SourceMgrPrinterTest.cpp @@ -32,39 +32,18 @@ class GroundTruthCollector [](DataFlowAnalysisType) { return ""; }, OS), GroundTruth(GroundTruth), OS(Str){}; - std::string findSubString(const std::string &String) { - size_t LastSlashPos = String.rfind('/'); - if (LastSlashPos != std::string::npos) { - // Find the first space after the last '/' - size_t FirstSpacePos = String.find(' ', LastSlashPos); - - if (FirstSpacePos != std::string::npos) { - // Extract the substring from the last '/' to the first space after - // the last '/' - std::string Result = - String.substr(LastSlashPos + 1, FirstSpacePos - LastSlashPos - 2); - return Result; +private: + void doOnFinalize() override { + for (auto It = GroundTruth.begin(); It != GroundTruth.end();) { + if (OS.str().find(*It)) { + GroundTruth.erase(It++); + } else { + ++It; } - return ""; } - return ""; - } - - void findAndRemove(const std::string &SearchString) { - std::string SubString = findSubString(SearchString); - GroundTruth.erase(SubString); + EXPECT_TRUE(GroundTruth.empty()); } - void onResult(n_t Instr, d_t DfFact, l_t LatticeElement, - DataFlowAnalysisType AnalysisType) override { - SourceMgrPrinter::onResult( - Instr, DfFact, LatticeElement, AnalysisType); - findAndRemove(OS.str()); - } - - void onFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } - -private: std::set GroundTruth{}; std::string Str; llvm::raw_string_ostream OS; From 479646f7451e0cb3f848a1e78ab8d918601a0b0e Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Wed, 14 Feb 2024 15:14:32 +0100 Subject: [PATCH 20/27] adding warning kind --- .../phasar/PhasarLLVM/Utils/SourceMgrPrinter.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index 5cb4768f76..dd1189efde 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -26,8 +26,9 @@ class SourceMgrPrinter : public AnalysisPrinterBase { public: SourceMgrPrinter( llvm::unique_function &&PrintMessage, - llvm::raw_ostream &OS = llvm::errs()) - : GetPrintMessage(std::move(PrintMessage)), OS(&OS) {} + llvm::raw_ostream &OS = llvm::errs(), + llvm::SourceMgr::DiagKind WKind = llvm::SourceMgr::DK_Warning) + : GetPrintMessage(std::move(PrintMessage)), OS(&OS), WarningKind(WKind) {} private: void doOnResult(n_t Instr, d_t /*DfFact*/, l_t /*Lattice*/, @@ -37,19 +38,20 @@ class SourceMgrPrinter : public AnalysisPrinterBase { if (BufIdOpt.has_value()) { std::pair LineAndCol = getLineAndColFromIR(Instr); - /// TODO: Configuration options for warning or error - SrcMgr.PrintMessage( - *OS, - SrcMgr.FindLocForLineAndColumn(BufIdOpt.value(), LineAndCol.first, - LineAndCol.second), - llvm::SourceMgr::DK_Warning, GetPrintMessage(AnalysisType)); + SrcMgr.PrintMessage(*OS, + SrcMgr.FindLocForLineAndColumn(BufIdOpt.value(), + LineAndCol.first, + LineAndCol.second), + WarningKind, GetPrintMessage(AnalysisType)); } } llvm::StringMap FileNameIDMap{}; llvm::SourceMgr SrcMgr{}; llvm::unique_function GetPrintMessage; + MaybeUniquePtr OS = &llvm::errs(); + llvm::SourceMgr::DiagKind WarningKind; }; } // namespace psr From 61afaa1b53943dd965e8278cedd3b58402f37fa8 Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Wed, 14 Feb 2024 17:39:16 +0100 Subject: [PATCH 21/27] fix ci --- .../DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 4862f12743..806cb58e2c 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -208,7 +208,7 @@ TEST_F(IDETaintAnalysisTest, XTaint09_1) { TEST_F(IDETaintAnalysisTest, XTaint09) { map> Gt; - Gt[25] = {"24"}; + Gt[34] = {"33"}; doAnalysis({PathToLLFiles + "xtaint09_cpp.ll"}, Gt, std::monostate{}); } From 0ae5d1fa0753d8e78251760606966d5d3c9767b0 Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Wed, 21 Feb 2024 17:07:33 +0100 Subject: [PATCH 22/27] update codeowners for analysis-printer --- .github/CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bfd339c160..3e74129213 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -26,3 +26,9 @@ Dockerfile @janniclas /.docker/ @janniclas /include/phasar/Utils/Logger.h @MMory +/include/phasar/Utils/AnalysisPrinterBase.h @sritejakv +/include/phasar/Utils/DefaultAnalysisPrinter.h @sritejakv +/include/phasar/Utils/NullAnalysisPrinter.h @sritejakv +/include/phasar/Utils/OnTheFlyAnalysisPrinter.h @sritejakv +/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @sritejakv +/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp @sritejakv From 90e13ef5d4ebfb7b5b11677efd57454b499f2fb9 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 21 Feb 2024 19:48:57 +0100 Subject: [PATCH 23/27] Refactor SourceManagerPrinter --- .clang-tidy | 1 + include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h | 11 ++ .../PhasarLLVM/Utils/LLVMSourceManager.h | 36 ++++++ .../PhasarLLVM/Utils/SourceMgrPrinter.h | 67 ++++++---- lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp | 118 +++++++++++------- lib/PhasarLLVM/Utils/LLVMSourceManager.cpp | 54 ++++++++ lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp | 28 ++--- .../ControlFlow/LLVMBasedICFGExportTest.cpp | 29 +++-- unittests/Utils/SourceMgrPrinterTest.cpp | 40 +++--- 9 files changed, 262 insertions(+), 122 deletions(-) create mode 100644 include/phasar/PhasarLLVM/Utils/LLVMSourceManager.h create mode 100644 lib/PhasarLLVM/Utils/LLVMSourceManager.cpp diff --git a/.clang-tidy b/.clang-tidy index 8447efed92..54f04105c7 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -4,6 +4,7 @@ Checks: '-*, misc-*, -misc-non-private-member-variables-in-classes, -misc-no-recursion, + -misc-use-anonymous-namespace, readability-*, -readability-function-cognitive-complexity, -readability-else-after*, diff --git a/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h b/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h index 17cab3ef96..9432e9c921 100644 --- a/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h +++ b/include/phasar/PhasarLLVM/Utils/LLVMIRToSrc.h @@ -19,6 +19,7 @@ #include "nlohmann/json.hpp" +#include #include // Forward declaration of types for which we only use its pointer or ref type @@ -39,6 +40,7 @@ namespace psr { [[nodiscard]] std::string getFunctionNameFromIR(const llvm::Value *V); [[nodiscard]] std::string getFilePathFromIR(const llvm::Value *V); +[[nodiscard]] std::string getFilePathFromIR(const llvm::DIFile *DIF); [[nodiscard]] std::string getDirectoryFromIR(const llvm::Value *V); @@ -85,6 +87,15 @@ void to_json(nlohmann::json &J, const SourceCodeInfo &Info); [[nodiscard]] SourceCodeInfo getSrcCodeInfoFromIR(const llvm::Value *V); +struct DebugLocation { + unsigned Line{}; + unsigned Column{}; + const llvm::DIFile *File{}; +}; + +[[nodiscard]] std::optional +getDebugLocation(const llvm::Value *V); + } // namespace psr #endif diff --git a/include/phasar/PhasarLLVM/Utils/LLVMSourceManager.h b/include/phasar/PhasarLLVM/Utils/LLVMSourceManager.h new file mode 100644 index 0000000000..1828c6e535 --- /dev/null +++ b/include/phasar/PhasarLLVM/Utils/LLVMSourceManager.h @@ -0,0 +1,36 @@ +#ifndef PHASAR_PHASARLLVM_UTILS_LLVMSOURCEMANAGER_H +#define PHASAR_PHASARLLVM_UTILS_LLVMSOURCEMANAGER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/SourceMgr.h" + +#include + +namespace llvm { +class Value; +class DIFile; +} // namespace llvm + +namespace psr { +struct ManagedDebugLocation { + unsigned Line{}; + unsigned Column{}; + unsigned File{}; +}; + +class LLVMSourceManager { +public: + [[nodiscard]] std::optional + getDebugLocation(const llvm::Value *V); + + void print(llvm::raw_ostream &OS, ManagedDebugLocation Loc, + llvm::SourceMgr::DiagKind DiagKind, const llvm::Twine &Message); + +private: + llvm::DenseMap FileIdMap{}; + llvm::SourceMgr SrcMgr{}; +}; +} // namespace psr + +#endif // PHASAR_PHASARLLVM_UTILS_LLVMSOURCEMANAGER_H diff --git a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h index dd1189efde..58b00e9a9c 100644 --- a/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h +++ b/include/phasar/PhasarLLVM/Utils/SourceMgrPrinter.h @@ -1,57 +1,70 @@ #ifndef PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H #define PHASAR_PHASARLLVM_UTILS_SOURCEMGRPRINTER_H + #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" +#include "phasar/PhasarLLVM/Utils/LLVMSourceManager.h" #include "phasar/Utils/AnalysisPrinterBase.h" -#include "phasar/Utils/Logger.h" #include "phasar/Utils/MaybeUniquePtr.h" #include "llvm/ADT/FunctionExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" +#include + namespace psr { -std::optional getSourceBufId(llvm::StringRef FileName, - llvm::StringMap &FileNameIDMap, - llvm::SourceMgr &SrcMgr); +namespace detail { +class SourceMgrPrinterBase { +public: + explicit SourceMgrPrinterBase( + llvm::unique_function &&PrintMessage, + llvm::raw_ostream &OS = llvm::errs(), + llvm::SourceMgr::DiagKind WKind = llvm::SourceMgr::DK_Warning); + + explicit SourceMgrPrinterBase( + llvm::unique_function &&PrintMessage, + const llvm::Twine &OutFileName, + llvm::SourceMgr::DiagKind WKind = llvm::SourceMgr::DK_Warning); + +protected: + LLVMSourceManager SrcMgr; + + llvm::unique_function GetPrintMessage; + MaybeUniquePtr OS = &llvm::errs(); + llvm::SourceMgr::DiagKind WarningKind; +}; +} // namespace detail template -class SourceMgrPrinter : public AnalysisPrinterBase { +class SourceMgrPrinter : public AnalysisPrinterBase, + private detail::SourceMgrPrinterBase { using n_t = typename AnalysisDomainTy::n_t; using d_t = typename AnalysisDomainTy::d_t; using l_t = typename AnalysisDomainTy::l_t; public: - SourceMgrPrinter( + explicit SourceMgrPrinter( llvm::unique_function &&PrintMessage, llvm::raw_ostream &OS = llvm::errs(), llvm::SourceMgr::DiagKind WKind = llvm::SourceMgr::DK_Warning) - : GetPrintMessage(std::move(PrintMessage)), OS(&OS), WarningKind(WKind) {} + : detail::SourceMgrPrinterBase(std::move(PrintMessage), OS, WKind) {} private: - void doOnResult(n_t Instr, d_t /*DfFact*/, l_t /*Lattice*/, + void doOnResult(n_t Inst, d_t Fact, l_t /*Value*/, DataFlowAnalysisType AnalysisType) override { - auto BufIdOpt = - getSourceBufId(getFilePathFromIR(Instr), FileNameIDMap, SrcMgr); - if (BufIdOpt.has_value()) { - std::pair LineAndCol = - getLineAndColFromIR(Instr); - SrcMgr.PrintMessage(*OS, - SrcMgr.FindLocForLineAndColumn(BufIdOpt.value(), - LineAndCol.first, - LineAndCol.second), - WarningKind, GetPrintMessage(AnalysisType)); + auto SrcLoc = SrcMgr.getDebugLocation(Inst); + if constexpr (std::is_convertible_v) { + if (!SrcLoc) { + SrcLoc = + SrcMgr.getDebugLocation(static_cast(Fact)); + } } - } - - llvm::StringMap FileNameIDMap{}; - llvm::SourceMgr SrcMgr{}; - llvm::unique_function GetPrintMessage; - MaybeUniquePtr OS = &llvm::errs(); - llvm::SourceMgr::DiagKind WarningKind; + if (SrcLoc) { + SrcMgr.print(*OS, *SrcLoc, WarningKind, GetPrintMessage(AnalysisType)); + } + } }; } // namespace psr diff --git a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp index d32c9a3adf..01dd076031 100644 --- a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp +++ b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp @@ -9,7 +9,7 @@ #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Demangle/Demangle.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -20,19 +20,17 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" - -#include "boost/algorithm/string/trim.hpp" +#include "llvm/Support/Path.h" #include #include #include +#include #include using namespace psr; -namespace psr { - -llvm::DbgVariableIntrinsic *getDbgVarIntrinsic(const llvm::Value *V) { +static llvm::DbgVariableIntrinsic *getDbgVarIntrinsic(const llvm::Value *V) { if (auto *VAM = llvm::ValueAsMetadata::getIfExists( const_cast(V))) { // NOLINT FIXME when LLVM supports it if (auto *MDV = llvm::MetadataAsValue::getIfExists(V->getContext(), VAM)) { @@ -58,7 +56,7 @@ llvm::DbgVariableIntrinsic *getDbgVarIntrinsic(const llvm::Value *V) { return nullptr; } -llvm::DILocalVariable *getDILocalVariable(const llvm::Value *V) { +static llvm::DILocalVariable *getDILocalVariable(const llvm::Value *V) { if (auto *DbgIntr = getDbgVarIntrinsic(V)) { if (auto *DDI = llvm::dyn_cast(DbgIntr)) { return DDI->getVariable(); @@ -70,7 +68,7 @@ llvm::DILocalVariable *getDILocalVariable(const llvm::Value *V) { return nullptr; } -llvm::DIGlobalVariable *getDIGlobalVariable(const llvm::Value *V) { +static llvm::DIGlobalVariable *getDIGlobalVariable(const llvm::Value *V) { if (const auto *GV = llvm::dyn_cast(V)) { if (auto *MN = GV->getMetadata(llvm::LLVMContext::MD_dbg)) { if (auto *DIGVExp = @@ -82,14 +80,14 @@ llvm::DIGlobalVariable *getDIGlobalVariable(const llvm::Value *V) { return nullptr; } -llvm::DISubprogram *getDISubprogram(const llvm::Value *V) { +static llvm::DISubprogram *getDISubprogram(const llvm::Value *V) { if (const auto *F = llvm::dyn_cast(V)) { return F->getSubprogram(); } return nullptr; } -llvm::DILocation *getDILocation(const llvm::Value *V) { +static llvm::DILocation *getDILocation(const llvm::Value *V) { // Arguments and Instruction such as AllocaInst if (auto *DbgIntr = getDbgVarIntrinsic(V)) { if (auto *MN = DbgIntr->getMetadata(llvm::LLVMContext::MD_dbg)) { @@ -103,7 +101,7 @@ llvm::DILocation *getDILocation(const llvm::Value *V) { return nullptr; } -std::string getVarNameFromIR(const llvm::Value *V) { +std::string psr::getVarNameFromIR(const llvm::Value *V) { if (auto *LocVar = getDILocalVariable(V)) { return LocVar->getName().str(); } @@ -113,7 +111,7 @@ std::string getVarNameFromIR(const llvm::Value *V) { return ""; } -std::string getFunctionNameFromIR(const llvm::Value *V) { +std::string psr::getFunctionNameFromIR(const llvm::Value *V) { // We can return unmangled function names w/o checking debug info if (const auto *F = llvm::dyn_cast(V)) { return F->getName().str(); @@ -127,35 +125,47 @@ std::string getFunctionNameFromIR(const llvm::Value *V) { return ""; } -std::string getFilePathFromIR(const llvm::Value *V) { +std::string psr::getFilePathFromIR(const llvm::Value *V) { if (const auto *DIF = getDIFileFromIR(V)) { - std::filesystem::path File(DIF->getFilename().str()); - std::filesystem::path Dir(DIF->getDirectory().str()); - if (!File.empty()) { - // try to concatenate file path and dir to get absolut path - if (!File.has_root_directory() && !Dir.empty()) { - File = Dir / File; - } - return File.string(); - } - } else { - /* As a fallback solution, we will return 'source_filename' info from - * module. However, it is not guaranteed to contain the absoult path, and it - * will return 'llvm-link' for linked modules. */ - if (const auto *F = llvm::dyn_cast(V)) { - return F->getParent()->getSourceFileName(); - } - if (const auto *Arg = llvm::dyn_cast(V)) { - return Arg->getParent()->getParent()->getSourceFileName(); - } - if (const auto *I = llvm::dyn_cast(V)) { - return I->getFunction()->getParent()->getSourceFileName(); - } + return getFilePathFromIR(DIF); } - return ""; + /* As a fallback solution, we will return 'source_filename' info from + * module. However, it is not guaranteed to contain the absoult path, and it + * will return 'llvm-link' for linked modules. */ + if (const auto *F = llvm::dyn_cast(V)) { + return F->getParent()->getSourceFileName(); + } + if (const auto *Arg = llvm::dyn_cast(V)) { + return Arg->getParent()->getParent()->getSourceFileName(); + } + if (const auto *I = llvm::dyn_cast(V)) { + return I->getFunction()->getParent()->getSourceFileName(); + } + + return {}; +} + +std::string psr::getFilePathFromIR(const llvm::DIFile *DIF) { + auto FileName = DIF->getFilename(); + auto DirName = DIF->getDirectory(); + + if (FileName.empty()) { + return {}; + } + + // try to concatenate file path and dir to get absolute path + if (!DirName.empty() && + !llvm::sys::path::has_root_directory(DIF->getFilename())) { + llvm::SmallString<256> Buf; + llvm::sys::path::append(Buf, DirName, FileName); + + return Buf.str().str(); + } + + return FileName.str(); } -const llvm::DIFile *getDIFileFromIR(const llvm::Value *V) { +const llvm::DIFile *psr::getDIFileFromIR(const llvm::Value *V) { if (const auto *GO = llvm::dyn_cast(V)) { if (auto *MN = GO->getMetadata(llvm::LLVMContext::MD_dbg)) { if (auto *Subpr = llvm::dyn_cast(MN)) { @@ -181,7 +191,7 @@ const llvm::DIFile *getDIFileFromIR(const llvm::Value *V) { return nullptr; } -std::string getDirectoryFromIR(const llvm::Value *V) { +std::string psr::getDirectoryFromIR(const llvm::Value *V) { // Argument and Instruction if (auto *DILoc = getDILocation(V)) { return DILoc->getDirectory().str(); @@ -195,7 +205,7 @@ std::string getDirectoryFromIR(const llvm::Value *V) { return ""; } -unsigned int getLineFromIR(const llvm::Value *V) { +unsigned int psr::getLineFromIR(const llvm::Value *V) { // Argument and Instruction if (auto *DILoc = getDILocation(V)) { return DILoc->getLine(); @@ -209,7 +219,7 @@ unsigned int getLineFromIR(const llvm::Value *V) { return 0; } -unsigned int getColumnFromIR(const llvm::Value *V) { +unsigned int psr::getColumnFromIR(const llvm::Value *V) { // Globals and Function have no column info if (auto *DILoc = getDILocation(V)) { return DILoc->getColumn(); @@ -217,7 +227,7 @@ unsigned int getColumnFromIR(const llvm::Value *V) { return 0; } -std::pair getLineAndColFromIR(const llvm::Value *V) { +std::pair psr::getLineAndColFromIR(const llvm::Value *V) { // Argument and Instruction if (auto *DILoc = getDILocation(V)) { return {DILoc->getLine(), DILoc->getColumn()}; @@ -231,7 +241,7 @@ std::pair getLineAndColFromIR(const llvm::Value *V) { return {0, 0}; } -std::string getSrcCodeFromIR(const llvm::Value *V, bool Trim) { +std::string psr::getSrcCodeFromIR(const llvm::Value *V, bool Trim) { unsigned int LineNr = getLineFromIR(V); if (LineNr > 0) { std::filesystem::path Path(getFilePathFromIR(V)); @@ -251,7 +261,7 @@ std::string getSrcCodeFromIR(const llvm::Value *V, bool Trim) { return ""; } -std::string getModuleIDFromIR(const llvm::Value *V) { +std::string psr::getModuleIDFromIR(const llvm::Value *V) { if (const auto *GO = llvm::dyn_cast(V)) { return GO->getParent()->getModuleIdentifier(); } @@ -294,7 +304,7 @@ bool SourceCodeInfo::equivalentWith(const SourceCodeInfo &Other) const { .slice(Pos + 1, llvm::StringRef::npos)); } -void from_json(const nlohmann::json &J, SourceCodeInfo &Info) { +void psr::from_json(const nlohmann::json &J, SourceCodeInfo &Info) { J.at("sourceCodeLine").get_to(Info.SourceCodeLine); J.at("sourceCodeFileName").get_to(Info.SourceCodeFilename); if (auto Fn = J.find("sourceCode"); Fn != J.end()) { @@ -303,7 +313,7 @@ void from_json(const nlohmann::json &J, SourceCodeInfo &Info) { J.at("line").get_to(Info.Line); J.at("column").get_to(Info.Column); } -void to_json(nlohmann::json &J, const SourceCodeInfo &Info) { +void psr::to_json(nlohmann::json &J, const SourceCodeInfo &Info) { J = nlohmann::json{ {"sourceCodeLine", Info.SourceCodeLine}, {"sourceCodeFileName", Info.SourceCodeFilename}, @@ -313,7 +323,7 @@ void to_json(nlohmann::json &J, const SourceCodeInfo &Info) { }; } -SourceCodeInfo getSrcCodeInfoFromIR(const llvm::Value *V) { +SourceCodeInfo psr::getSrcCodeInfoFromIR(const llvm::Value *V) { return SourceCodeInfo{ getSrcCodeFromIR(V), getFilePathFromIR(V), @@ -323,4 +333,18 @@ SourceCodeInfo getSrcCodeInfoFromIR(const llvm::Value *V) { }; } -} // namespace psr +std::optional psr::getDebugLocation(const llvm::Value *V) { + // Argument and Instruction + if (auto *DILoc = getDILocation(V)) { + return DebugLocation{DILoc->getLine(), DILoc->getColumn(), + DILoc->getFile()}; + } + if (auto *DISubpr = getDISubprogram(V)) { // Function + return DebugLocation{DISubpr->getLine(), 0, DISubpr->getFile()}; + } + if (auto *DIGV = getDIGlobalVariable(V)) { // Globals + return DebugLocation{DIGV->getLine(), 0, DIGV->getFile()}; + } + + return std::nullopt; +} diff --git a/lib/PhasarLLVM/Utils/LLVMSourceManager.cpp b/lib/PhasarLLVM/Utils/LLVMSourceManager.cpp new file mode 100644 index 0000000000..dba8f48091 --- /dev/null +++ b/lib/PhasarLLVM/Utils/LLVMSourceManager.cpp @@ -0,0 +1,54 @@ +#include "phasar/PhasarLLVM/Utils/LLVMSourceManager.h" + +#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" +#include "phasar/Utils/Logger.h" + +#include "llvm/IR/DebugInfoMetadata.h" + +#include + +using namespace psr; + +static std::optional +getSourceBufId(const llvm::DIFile *File, + llvm::DenseMap &FileIdMap, + llvm::SourceMgr &SrcMgr) { + if (auto It = FileIdMap.find(File); It != FileIdMap.end()) { + return It->second; + } + + auto FileName = psr::getFilePathFromIR(File); + auto Buf = llvm::MemoryBuffer::getFile(FileName, true); + if (!Buf) { + PHASAR_LOG_LEVEL(WARNING, "Source File not accessible: " << FileName); + PHASAR_LOG_LEVEL(INFO, "> " << Buf.getError().message()); + return std::nullopt; + } + + auto Id = SrcMgr.AddNewSourceBuffer(std::move(Buf.get()), llvm::SMLoc{}); + FileIdMap.try_emplace(File, Id); + return Id; +} + +std::optional +LLVMSourceManager::getDebugLocation(const llvm::Value *V) { + auto Loc = psr::getDebugLocation(V); + if (!Loc) { + return std::nullopt; + } + + auto BufId = getSourceBufId(Loc->File, FileIdMap, SrcMgr); + if (!BufId) { + return std::nullopt; + } + + return ManagedDebugLocation{Loc->Line, Loc->Column, *BufId}; +} + +void LLVMSourceManager::print(llvm::raw_ostream &OS, ManagedDebugLocation Loc, + llvm::SourceMgr::DiagKind DiagKind, + const llvm::Twine &Message) { + auto SMLoc = SrcMgr.FindLocForLineAndColumn(Loc.File, Loc.Line, Loc.Column); + + SrcMgr.PrintMessage(OS, SMLoc, DiagKind, Message); +} diff --git a/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp b/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp index b2205670fa..01687a5dcf 100644 --- a/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp +++ b/lib/PhasarLLVM/Utils/SourceMgrPrinter.cpp @@ -1,22 +1,16 @@ #include "phasar/PhasarLLVM/Utils/SourceMgrPrinter.h" -namespace psr { +#include "phasar/Utils/IO.h" -std::optional getSourceBufId(llvm::StringRef FileName, - llvm::StringMap &FileNameIDMap, - llvm::SourceMgr &SrcMgr) { - if (auto It = FileNameIDMap.find(FileName); It != FileNameIDMap.end()) { - return It->second; - } +using namespace psr; - auto Buf = llvm::MemoryBuffer::getFile(FileName, true); - if (!Buf) { - PHASAR_LOG_LEVEL(WARNING, "File not accessible: " << FileName); - return std::nullopt; - } +detail::SourceMgrPrinterBase::SourceMgrPrinterBase( + llvm::unique_function &&PrintMessage, + llvm::raw_ostream &OS, llvm::SourceMgr::DiagKind WKind) + : GetPrintMessage(std::move(PrintMessage)), OS(&OS), WarningKind(WKind) {} - auto Id = SrcMgr.AddNewSourceBuffer(std::move(Buf.get()), llvm::SMLoc{}); - FileNameIDMap.try_emplace(FileName, Id); - return Id; -} -} // namespace psr +detail::SourceMgrPrinterBase::SourceMgrPrinterBase( + llvm::unique_function &&PrintMessage, + const llvm::Twine &OutFileName, llvm::SourceMgr::DiagKind WKind) + : GetPrintMessage(std::move(PrintMessage)), OS(openFileStream(OutFileName)), + WarningKind(WKind) {} diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGExportTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGExportTest.cpp index 9b4b180468..18f503fc3d 100644 --- a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGExportTest.cpp +++ b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGExportTest.cpp @@ -152,20 +152,27 @@ class LLVMBasedICFGExportTest : public ::testing::Test { ASSERT_TRUE(ExportedICFG.is_array()); EXPECT_EQ(GroundTruth.size(), ExportedICFG.size()); - + bool HasError = false; for (const auto >Json : GroundTruth) { auto GTFrom = GTJson.at("from").get(); auto GTTo = GTJson.at("to").get(); - EXPECT_TRUE(std::any_of(ExportedICFG.begin(), ExportedICFG.end(), - [&](const nlohmann::json &ExportedInfoJson) { - return ExportedInfoJson.at("from") - .get() - .equivalentWith(GTFrom) && - ExportedInfoJson.at("to") - .get() - .equivalentWith(GTTo); - })) - << "No exported equivalent to " << GTJson.dump(4); + + bool HasMatch = std::any_of(ExportedICFG.begin(), ExportedICFG.end(), + [&](const nlohmann::json &ExportedInfoJson) { + return ExportedInfoJson.at("from") + .get() + .equivalentWith(GTFrom) && + ExportedInfoJson.at("to") + .get() + .equivalentWith(GTTo); + }); + + EXPECT_TRUE(HasMatch) << "No exported equivalent to " << GTJson.dump(4); + HasError |= !HasMatch; + } + + if (HasError) { + llvm::errs() << "Errorneous json: " << ExportedICFG.dump(4) << '\n'; } } diff --git a/unittests/Utils/SourceMgrPrinterTest.cpp b/unittests/Utils/SourceMgrPrinterTest.cpp index 8fda921828..59f4fc69a0 100644 --- a/unittests/Utils/SourceMgrPrinterTest.cpp +++ b/unittests/Utils/SourceMgrPrinterTest.cpp @@ -15,10 +15,11 @@ #include "TestConfig.h" #include "gtest/gtest.h" +#include #include using namespace psr; - +namespace { class GroundTruthCollector : public SourceMgrPrinter { using n_t = LLVMIFDSAnalysisDomainDefault::n_t; @@ -27,10 +28,11 @@ class GroundTruthCollector public: // constructor init Groundtruth in each fixture - GroundTruthCollector(std::set &GroundTruth) + GroundTruthCollector(std::initializer_list GroundTruth, + bool Dump = false) : SourceMgrPrinter( [](DataFlowAnalysisType) { return ""; }, OS), - GroundTruth(GroundTruth), OS(Str){}; + GroundTruth(GroundTruth), OS(Str), Dump(Dump){}; private: void doOnFinalize() override { @@ -42,11 +44,16 @@ class GroundTruthCollector } } EXPECT_TRUE(GroundTruth.empty()); + + if (Dump) { + llvm::errs() << Str << '\n'; + } } std::set GroundTruth{}; std::string Str; llvm::raw_string_ostream OS; + bool Dump{}; }; class SourceMgrPrinterTest : public ::testing::Test { @@ -55,21 +62,17 @@ class SourceMgrPrinterTest : public ::testing::Test { PHASAR_BUILD_SUBFOLDER("uninitialized_variables/"); const std::vector EntryPoints = {"main"}; - std::optional UnInitProblem; - std::optional HA; - - void initialize(const llvm::Twine &IRFile) { - HA.emplace(PathToLlFiles + IRFile, EntryPoints); - UnInitProblem = - createAnalysisProblem(*HA, EntryPoints); - } void doAnalysisTest( llvm::StringRef IRFile, AnalysisPrinterBase >Printer) { - initialize(IRFile); - UnInitProblem->setAnalysisPrinter(>Printer); - IFDSSolver Solver(*UnInitProblem, &HA->getICFG()); + HelperAnalyses HA(PathToLlFiles + IRFile, EntryPoints); + auto UnInitProblem = + createAnalysisProblem(HA, EntryPoints); + + UnInitProblem.setAnalysisPrinter(>Printer); + GTPrinter.onInitialize(); + IFDSSolver Solver(UnInitProblem, &HA.getICFG()); Solver.solve(); GTPrinter.onFinalize(); } @@ -78,15 +81,12 @@ class SourceMgrPrinterTest : public ::testing::Test { /* ============== BASIC TESTS ============== */ TEST_F(SourceMgrPrinterTest, UninitTest_01_LEAK) { - - std::set GroundTruth; - - GroundTruth = {"binop_uninit.cpp:3:11", "binop_uninit.cpp:3:13"}; - - GroundTruthCollector GroundTruthPrinter = {GroundTruth}; + GroundTruthCollector GroundTruthPrinter( + {"/binop_uninit.cpp:3:11:", "/binop_uninit.cpp:3:13:"}); doAnalysisTest("binop_uninit_cpp_dbg.ll", GroundTruthPrinter); } +} // namespace // main function for the test case int main(int Argc, char **Argv) { From 824490d85d176933c18dee0301f5cd76348943b0 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 21 Feb 2024 20:11:12 +0100 Subject: [PATCH 24/27] Minor in OTF Printer Test --- .../Utils/OnTheFlyAnalysisPrinterTest.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp index 51d793ec11..f3cd874d5a 100644 --- a/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp +++ b/unittests/Utils/OnTheFlyAnalysisPrinterTest.cpp @@ -8,7 +8,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/raw_ostream.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -26,26 +25,27 @@ class GroundTruthCollector GroundTruthCollector(llvm::DenseMap> &GroundTruth) : GroundTruth(GroundTruth){}; - void findAndRemove(llvm::DenseMap> &Map1, - llvm::DenseMap> &Map2) { - for (auto Entry = Map1.begin(); Entry != Map1.end();) { - auto Iter = Map2.find(Entry->first); - if (Iter != Map2.end() && Iter->second == Entry->second) { - Map2.erase(Iter); - } - ++Entry; + void findAndRemove(int LeakId, const std::string &LeakedFactId) { + + auto It = GroundTruth.find(LeakId); + ASSERT_NE(It, GroundTruth.end()) + << "Found leak at unexpected location: " << LeakId << ": '" + << LeakedFactId << "'"; + + bool Erased = It->second.erase(LeakedFactId); + ASSERT_TRUE(Erased) << "Did not expect leak '" << LeakedFactId + << "' at instruction " << LeakId; + + if (It->second.empty()) { + GroundTruth.erase(It); } } private: void doOnResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, DataFlowAnalysisType /*AnalysisType*/) override { - llvm::DenseMap> FoundLeak; - int SinkId = stoi(getMetaDataID(Instr)); - std::set LeakedValueIds; - LeakedValueIds.insert(getMetaDataID((DfFact))); - FoundLeak.try_emplace(SinkId, LeakedValueIds); - findAndRemove(FoundLeak, GroundTruth); + int LeakId = stoi(getMetaDataID(Instr)); + findAndRemove(LeakId, getMetaDataID(DfFact)); } void doOnFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } From 9a17c912c2a47c080f8b57120b6631c6eed43a7a Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Wed, 21 Feb 2024 21:42:28 +0100 Subject: [PATCH 25/27] fixing review feedback --- include/phasar/Utils/DefaultAnalysisPrinter.h | 8 +++++++- include/phasar/Utils/OnTheFlyAnalysisPrinter.h | 9 ++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/phasar/Utils/DefaultAnalysisPrinter.h b/include/phasar/Utils/DefaultAnalysisPrinter.h index fcf4aeb13c..ee956cc791 100644 --- a/include/phasar/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/Utils/DefaultAnalysisPrinter.h @@ -3,6 +3,7 @@ #include "phasar/Domain/BinaryDomain.h" #include "phasar/Utils/AnalysisPrinterBase.h" +#include "phasar/Utils/IO.h" #include "phasar/Utils/MaybeUniquePtr.h" #include "phasar/Utils/Printer.h" @@ -36,8 +37,13 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { using l_t = typename AnalysisDomainTy::l_t; public: + explicit DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) + : OS(&OS) {} + + explicit DefaultAnalysisPrinter(const llvm::Twine &Filename) + : AnalysisPrinterBase(), OS(openFileStream(Filename)){}; + ~DefaultAnalysisPrinter() override = default; - DefaultAnalysisPrinter(llvm::raw_ostream &OS = llvm::outs()) : OS(&OS) {} private: void doOnResult(n_t Instr, d_t DfFact, l_t Lattice, diff --git a/include/phasar/Utils/OnTheFlyAnalysisPrinter.h b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h index 08be84dda7..aa3e4ef232 100644 --- a/include/phasar/Utils/OnTheFlyAnalysisPrinter.h +++ b/include/phasar/Utils/OnTheFlyAnalysisPrinter.h @@ -23,12 +23,11 @@ class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { explicit OnTheFlyAnalysisPrinter(llvm::raw_ostream &OS) : AnalysisPrinterBase(), OS(&OS){}; - explicit OnTheFlyAnalysisPrinter( - const llvm::Twine &Filename) + explicit OnTheFlyAnalysisPrinter(const llvm::Twine &Filename) : AnalysisPrinterBase(), OS(openFileStream(Filename)){}; - OnTheFlyAnalysisPrinter() = default; - ~OnTheFlyAnalysisPrinter() = default; + OnTheFlyAnalysisPrinter() = default; + ~OnTheFlyAnalysisPrinter() = default; [[nodiscard]] bool isValid() const noexcept { return OS != nullptr; } @@ -38,7 +37,7 @@ class OnTheFlyAnalysisPrinter : public AnalysisPrinterBase { assert(isValid()); *OS << "\nAt IR statement: " << NToString(Instr) << "\n"; *OS << "\tFact: " << DToString(DfFact) << "\n"; - if constexpr (std::is_same_v) { + if constexpr (!std::is_same_v) { *OS << "Value: " << LToString(LatticeElement) << "\n"; } } From b7539ec6d4f69a026b2f242c3c9dd0b36e12f5eb Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Thu, 22 Feb 2024 09:21:00 +0100 Subject: [PATCH 26/27] fix l_t printing --- include/phasar/Utils/DefaultAnalysisPrinter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/phasar/Utils/DefaultAnalysisPrinter.h b/include/phasar/Utils/DefaultAnalysisPrinter.h index ee956cc791..f9008b9461 100644 --- a/include/phasar/Utils/DefaultAnalysisPrinter.h +++ b/include/phasar/Utils/DefaultAnalysisPrinter.h @@ -58,7 +58,7 @@ class DefaultAnalysisPrinter : public AnalysisPrinterBase { *OS << "\tFact: " << DToString(Iter.Fact) << "\n"; - if constexpr (std::is_same_v) { + if constexpr (!std::is_same_v) { *OS << "Value: " << LToString(Iter.LatticeElement) << "\n"; } } From f8d46e90474eea0eed44b723323041e34ef7093e Mon Sep 17 00:00:00 2001 From: Sriteja Kummita Date: Fri, 23 Feb 2024 10:36:44 +0100 Subject: [PATCH 27/27] Mandating analysisType to tyestate descriptions --- .../DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h | 4 ++-- .../TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h | 1 + .../TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h | 1 + .../TypeStateDescriptions/OpenSSLEVPKDFDescription.h | 2 ++ .../TypeStateDescriptions/OpenSSLSecureHeapDescription.h | 1 + .../TypeStateDescriptions/OpenSSLSecureMemoryDescription.h | 1 + .../Problems/TypeStateDescriptions/TypeStateDescription.h | 3 +++ .../TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp | 5 +++++ .../TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.cpp | 5 +++++ .../TypeStateDescriptions/OpenSSLEVPKDFDescription.cpp | 5 +++++ .../TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp | 5 +++++ .../TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp | 5 +++++ 12 files changed, 36 insertions(+), 2 deletions(-) diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index ab579bbef1..be868e5605 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -532,7 +532,7 @@ class IDETypeStateAnalysis if (Res.second == TSD->error()) { // ERROR STATE DETECTED this->Printer->onResult(&I, Res.first, TSD->error(), - DataFlowAnalysisType::None); + TSD->analysisType()); } } } @@ -543,7 +543,7 @@ class IDETypeStateAnalysis if (Res.second == TSD->error()) { // ERROR STATE DETECTED this->Printer->onResult(&I, Res.first, TSD->error(), - DataFlowAnalysisType::None); + TSD->analysisType()); } } } diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h index 1f28206d17..c7cad79756 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h @@ -72,6 +72,7 @@ class CSTDFILEIOTypeStateDescription [[nodiscard]] TypeStateDescription::State uninit() const override; [[nodiscard]] TypeStateDescription::State start() const override; [[nodiscard]] TypeStateDescription::State error() const override; + [[nodiscard]] DataFlowAnalysisType analysisType() const override; }; extern template class IDETypeStateAnalysis; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h index 081b94a46a..144d3571c4 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h @@ -102,6 +102,7 @@ class OpenSSLEVPKDFCTXDescription [[nodiscard]] State uninit() const override; [[nodiscard]] State start() const override; [[nodiscard]] State error() const override; + [[nodiscard]] DataFlowAnalysisType analysisType() const override; /* /// Checks all callSites, where a EVP_KDF object needs to be in a /// certain state, such that the state transition for EVP_KDF_CTX is valid. diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h index 34023c863a..324333c623 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h @@ -85,6 +85,8 @@ class OpenSSLEVPKDFDescription [[nodiscard]] TypeStateDescription::State start() const override; [[nodiscard]] TypeStateDescription::State error() const override; + + [[nodiscard]] DataFlowAnalysisType analysisType() const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h index cb69f4fe7e..597fa27955 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h @@ -72,6 +72,7 @@ class OpenSSLSecureHeapDescription [[nodiscard]] TypeStateDescription::State uninit() const override; [[nodiscard]] TypeStateDescription::State start() const override; [[nodiscard]] TypeStateDescription::State error() const override; + [[nodiscard]] DataFlowAnalysisType analysisType() const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h index a1c41d1c27..57c41710c6 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h @@ -41,6 +41,7 @@ class OpenSSLSecureMemoryDescription [[nodiscard]] TypeStateDescription::State uninit() const override; [[nodiscard]] TypeStateDescription::State start() const override; [[nodiscard]] TypeStateDescription::State error() const override; + [[nodiscard]] DataFlowAnalysisType analysisType() const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h index 883b1d89d6..a7e14e8fc0 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h @@ -10,6 +10,8 @@ #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_TYPESTATEDESCRIPTIONS_TYPESTATEDESCRIPTION_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_TYPESTATEDESCRIPTIONS_TYPESTATEDESCRIPTION_H +#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" + #include "llvm/IR/InstrTypes.h" #include @@ -28,6 +30,7 @@ struct TypeStateDescriptionBase { getConsumerParamIdx(llvm::StringRef F) const = 0; [[nodiscard]] virtual std::set getFactoryParamIdx(llvm::StringRef F) const = 0; + [[nodiscard]] virtual DataFlowAnalysisType analysisType() const = 0; }; /** diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp index ba640d0bab..018ac4d93b 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp @@ -192,6 +192,11 @@ CSTDFILEIOState CSTDFILEIOTypeStateDescription::error() const { return CSTDFILEIOState::ERROR; } +[[nodiscard]] DataFlowAnalysisType +CSTDFILEIOTypeStateDescription::analysisType() const { + return DataFlowAnalysisType::IDECSTDIOTypeStateAnalysis; +} + template class IDETypeStateAnalysis; } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.cpp index df37f0bcb6..38a4e22af1 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.cpp @@ -194,6 +194,11 @@ OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::error() const { return OpenSSLEVPKDFCTXState::ERROR; } +[[nodiscard]] DataFlowAnalysisType +OpenSSLEVPKDFCTXDescription::analysisType() const { + return DataFlowAnalysisType::IDEOpenSSLTypeStateAnalysis; +} + OpenSSLEVPKDFCTXDescription::OpenSSLEVTKDFToken OpenSSLEVPKDFCTXDescription::funcNameToToken(llvm::StringRef F) { if (F == "EVP_KDF_CTX_new") { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.cpp index 4c0973cf7e..d881af8ad6 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.cpp @@ -130,6 +130,11 @@ OpenSSLEVPKDFState OpenSSLEVPKDFDescription::error() const { return OpenSSLEVPKDFState::ERROR; } +[[nodiscard]] DataFlowAnalysisType +OpenSSLEVPKDFDescription::analysisType() const { + return DataFlowAnalysisType::IDEOpenSSLTypeStateAnalysis; +} + OpenSSLEVPKDFDescription::OpenSSLEVTKDFToken OpenSSLEVPKDFDescription::funcNameToToken(llvm::StringRef FuncName) { if (FuncName == "EVP_KDF_fetch") { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp index 3c0a90a67f..716f682a4f 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp @@ -168,6 +168,11 @@ OpenSSLSecureHeapState OpenSSLSecureHeapDescription::error() const { return OpenSSLSecureHeapState::ERROR; } +[[nodiscard]] DataFlowAnalysisType +OpenSSLSecureHeapDescription::analysisType() const { + return DataFlowAnalysisType::IDEOpenSSLTypeStateAnalysis; +} + OpenSSLSecureHeapDescription::OpenSSLSecureHeapToken OpenSSLSecureHeapDescription::funcNameToToken(llvm::StringRef F) { return llvm::StringSwitch(F) diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp index 04d8eba6ef..a67f17e42b 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp @@ -170,4 +170,9 @@ OpenSSLSecureMemoryState OpenSSLSecureMemoryDescription::error() const { return OpenSSLSecureMemoryState::ERROR; } +[[nodiscard]] DataFlowAnalysisType +OpenSSLSecureMemoryDescription::analysisType() const { + return DataFlowAnalysisType::IDEOpenSSLTypeStateAnalysis; +} + } // namespace psr