From 1e9f3b725b6c11c1a66002ef5d7af553434b006b Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Sat, 25 Nov 2023 12:39:02 +0100 Subject: [PATCH] Analysis Printer (#677) * 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 * fix: review feedback --------- 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 ab20dc3f6..35bd80ae5 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 10253527c..01ff03246 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 9335838f9..19bdd525a 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> + Warn(&I, Res.first, TSD->error()); + // ERROR STATE DETECTED + this->Printer->onResult(Warn); } - } 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> + Warn(&I, Res.first, TSD->error()); + // ERROR STATE DETECTED + this->Printer->onResult(Warn); } - } 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 000000000..9190ead07 --- /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 DataflowAnalysisResults { + 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 000000000..7cbdf476b --- /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: + DataflowAnalysisResults 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 000000000..900767755 --- /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 d3dd8fd76..6759ed4b9 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 Warn( + Inst, makeFlowFact(LeakCandidate), Top{}); + Printer->onResult(Warn); } } @@ -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 Warn(Inst, makeFlowFact(Leak), + Top{}); + Printer->onResult(Warn); } } - 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 2877e3086..d65e8ea9c 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 8b1eb7341..53d6099e7 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 c7b2b6f72..a6ee4458b 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 Warn(CallSite, Source, + topElement()); + Printer->onResult(Warn); + } } 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 Warn(CallSite, Source, + topElement()); + Printer->onResult(Warn); + } } 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 e71e30b0e..04d8eba6e 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 000000000..8f1dfb70f --- /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 4edc79c48..fea979d61 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)