From 1d12b81319e9f82355c9492472910c5bc016db19 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 2 Aug 2023 19:24:29 +0200 Subject: [PATCH 1/4] Add default implementation for allTopFunction() --- .../DataFlow/IfdsIde/IDETabulationProblem.h | 31 ++++++++++++++----- .../DataFlow/IfdsIde/IFDSTabulationProblem.h | 2 -- .../Problems/IDEExtendedTaintAnalysis.h | 10 ------ .../Problems/IDEInstInteractionAnalysis.h | 2 -- .../Problems/IDELinearConstantAnalysis.h | 2 -- .../Problems/IDESecureHeapPropagation.h | 8 ----- .../Problems/IDEExtendedTaintAnalysis.cpp | 15 --------- .../Problems/IDELinearConstantAnalysis.cpp | 4 --- .../Problems/IDESecureHeapPropagation.cpp | 26 ---------------- 9 files changed, 24 insertions(+), 76 deletions(-) diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index 8f79ed8b4d..3d2bde9e60 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -12,6 +12,7 @@ #include "phasar/ControlFlow/ICFGBase.h" #include "phasar/DB/ProjectIRDBBase.h" +#include "phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h" #include "phasar/DataFlow/IfdsIde/EdgeFunctions.h" #include "phasar/DataFlow/IfdsIde/EntryPointUtils.h" #include "phasar/DataFlow/IfdsIde/FlowFunctions.h" @@ -36,6 +37,23 @@ namespace psr { struct HasNoConfigurationType; +template class AllTopFnProvider { +public: + /// Returns an edge function that represents the top element of the analysis. + virtual EdgeFunction allTopFunction() = 0; +}; + +template +class AllTopFnProvider< + AnalysisDomainTy, + std::enable_if_t>> { +public: + /// Returns an edge function that represents the top element of the analysis. + virtual EdgeFunction allTopFunction() { + return AllTop{}; + } +}; + template > class IDETabulationProblem : public FlowFunctions, @@ -44,7 +62,8 @@ class IDETabulationProblem : public FlowFunctions, public FunctionPrinter, public EdgeFunctions, public JoinLattice, - public EdgeFactPrinter { + public EdgeFactPrinter, + public AllTopFnProvider { public: using ProblemAnalysisDomain = AnalysisDomainTy; using d_t = typename AnalysisDomainTy::d_t; @@ -68,9 +87,6 @@ class IDETabulationProblem : public FlowFunctions, ~IDETabulationProblem() override = default; - /// Returns an edge function that represents the top element of the analysis. - virtual EdgeFunction allTopFunction() = 0; - /// Checks if the given data-flow fact is the special tautological lambda (or /// zero) fact. [[nodiscard]] virtual bool isZeroValue(d_t FlowFact) const { @@ -88,18 +104,19 @@ class IDETabulationProblem : public FlowFunctions, return *ZeroValue; } - void initializeZeroValue(d_t Zero) { + void initializeZeroValue(d_t Zero) noexcept( + std::is_nothrow_assignable_v &, d_t &&>) { assert(!ZeroValue.has_value()); ZeroValue = std::move(Zero); } /// Sets the configuration to be used by the IFDS/IDE solver. - void setIFDSIDESolverConfig(IFDSIDESolverConfig Config) { + void setIFDSIDESolverConfig(IFDSIDESolverConfig Config) noexcept { SolverConfig = Config; } /// Returns the configuration of the IFDS/IDE solver. - [[nodiscard]] IFDSIDESolverConfig &getIFDSIDESolverConfig() { + [[nodiscard]] IFDSIDESolverConfig &getIFDSIDESolverConfig() noexcept { return SolverConfig; } diff --git a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h index 5c6cb20597..59914521be 100644 --- a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h @@ -77,8 +77,6 @@ class IFDSTabulationProblem return EdgeIdentity{}; } - EdgeFunction allTopFunction() final { return AllTop{}; } - void printEdgeFact(llvm::raw_ostream &OS, BinaryDomain Val) const final { OS << Val; } diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h index 8a9979b522..bcbf03137f 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h @@ -248,16 +248,6 @@ class IDEExtendedTaintAnalysis [[nodiscard]] bool isZeroValue(d_t Fact) const override; - EdgeFunctionType allTopFunction() override; - - // JoinLattice - - l_t topElement() override; - - l_t bottomElement() override; - - l_t join(l_t LHS, l_t RHS) override; - // Printing functions void printNode(llvm::raw_ostream &OS, n_t Inst) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index ca75d1c127..2354050421 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -946,8 +946,6 @@ class IDEInstInteractionAnalysisT inline l_t join(l_t Lhs, l_t Rhs) override { return joinImpl(Lhs, Rhs); } - inline EdgeFunctionType allTopFunction() override { return AllTop(); } - // Provide some handy helper edge functions to improve reuse. // Edge function that kills all labels in a set (and may replaces them with diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h index 14e84327ce..770ff03aa7 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h @@ -117,8 +117,6 @@ class IDELinearConstantAnalysis EdgeFunction getSummaryEdgeFunction(n_t Curr, d_t CurrNode, n_t Succ, d_t SuccNode) override; - EdgeFunction allTopFunction() override; - // Helper functions void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h index 51663d05cd..4dc6e1c5b6 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h @@ -110,14 +110,6 @@ class IDESecureHeapPropagation n_t RetSite, d_t RetSiteNode) override; - l_t topElement() override; - - l_t bottomElement() override; - - l_t join(l_t Lhs, l_t Rhs) override; - - EdgeFunction allTopFunction() override; - void printEdgeFact(llvm::raw_ostream &OS, l_t L) const override; void emitTextReport(const SolverResults &SR, diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index 38c07cbf51..ca4846b5c9 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -69,11 +69,6 @@ bool IDEExtendedTaintAnalysis::isZeroValue(d_t Fact) const { return Fact->isZero(); } -IDEExtendedTaintAnalysis::EdgeFunctionType -IDEExtendedTaintAnalysis::allTopFunction() { - return AllTop{}; -} - // Flow functions: IDEExtendedTaintAnalysis::FlowFunctionPtrType @@ -786,16 +781,6 @@ void IDEExtendedTaintAnalysis::emitTextReport( OS << '\n'; } -// JoinLattice - -auto IDEExtendedTaintAnalysis::topElement() -> l_t { return Top{}; } - -auto IDEExtendedTaintAnalysis::bottomElement() -> l_t { return Bottom{}; } - -auto IDEExtendedTaintAnalysis::join(l_t LHS, l_t RHS) -> l_t { - return LHS.join(RHS, &BBO); -} - // Helpers: auto IDEExtendedTaintAnalysis::makeFlowFact(const llvm::Value *V) -> d_t { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index fd4b8908e5..98abfabbde 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -564,10 +564,6 @@ IDELinearConstantAnalysis::getSummaryEdgeFunction(n_t Curr, d_t CurrNode, return EdgeIdentity{}; } -EdgeFunction IDELinearConstantAnalysis::allTopFunction() { - return AllTop{}; -} - void IDELinearConstantAnalysis::printNode(llvm::raw_ostream &OS, n_t Stmt) const { OS << llvmIRToString(Stmt); diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp index 14706b7df5..6e7d869da9 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp @@ -187,32 +187,6 @@ IDESecureHeapPropagation::getSummaryEdgeFunction(n_t /*CallSite*/, return nullptr; } -IDESecureHeapPropagation::l_t IDESecureHeapPropagation::topElement() { - return l_t::TOP; -} - -IDESecureHeapPropagation::l_t IDESecureHeapPropagation::bottomElement() { - return l_t::BOT; -} - -IDESecureHeapPropagation::l_t IDESecureHeapPropagation::join(l_t Lhs, l_t Rhs) { - if (Lhs == Rhs) { - return Lhs; - } - if (Lhs == l_t::TOP) { - return Rhs; - } - if (Rhs == l_t::TOP) { - return Lhs; - } - return l_t::BOT; -} - -EdgeFunction -IDESecureHeapPropagation::allTopFunction() { - return AllTop{}; -} - void IDESecureHeapPropagation::printEdgeFact(llvm::raw_ostream &Os, l_t L) const { switch (L) { From 9bde4c9453a44537eb09a2cf4bbc0d061699964a Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 2 Aug 2023 20:55:23 +0200 Subject: [PATCH 2/4] Move the default flow function templates to their own class allowing container_type to be deduced (towards specifying sth else than std::set) --- .../phasar/DataFlow/IfdsIde/FlowFunctions.h | 940 +++++++++--------- .../DataFlow/IfdsIde/IDETabulationProblem.h | 14 +- .../DataFlow/IfdsIde/LLVMFlowFunctions.h | 21 - .../DataFlow/IfdsIde/LLVMZeroValue.h | 2 +- .../Problems/IDEExtendedTaintAnalysis.h | 2 +- .../IDEGeneralizedLCA/IDEGeneralizedLCA.h | 2 +- .../Problems/IDEInstInteractionAnalysis.h | 32 +- .../Problems/IDELinearConstantAnalysis.h | 2 +- .../IfdsIde/Problems/IDEProtoAnalysis.h | 2 +- .../Problems/IDESecureHeapPropagation.h | 2 +- .../DataFlow/IfdsIde/Problems/IDESolverTest.h | 2 +- .../IfdsIde/Problems/IDETypeStateAnalysis.h | 2 +- .../IfdsIde/Problems/IFDSConstAnalysis.h | 2 +- .../Problems/IFDSFieldSensTaintAnalysis.h | 2 +- .../IfdsIde/Problems/IFDSProtoAnalysis.h | 2 +- .../IfdsIde/Problems/IFDSSignAnalysis.h | 2 +- .../IfdsIde/Problems/IFDSSolverTest.h | 2 +- .../IfdsIde/Problems/IFDSTaintAnalysis.h | 2 +- .../IfdsIde/Problems/IFDSTypeAnalysis.h | 2 +- .../Problems/IFDSUninitializedVariables.h | 2 +- include/phasar/Utils/TypeTraits.h | 12 + .../Problems/IDEExtendedTaintAnalysis.cpp | 35 +- .../IDEGeneralizedLCA/IDEGeneralizedLCA.cpp | 35 +- .../Problems/IDELinearConstantAnalysis.cpp | 16 +- .../IfdsIde/Problems/IDEProtoAnalysis.cpp | 10 +- .../Problems/IDESecureHeapPropagation.cpp | 10 +- .../IfdsIde/Problems/IDESolverTest.cpp | 10 +- .../IfdsIde/Problems/IDETypeStateAnalysis.cpp | 13 +- .../IfdsIde/Problems/IFDSConstAnalysis.cpp | 13 +- .../IfdsIde/Problems/IFDSProtoAnalysis.cpp | 13 +- .../IfdsIde/Problems/IFDSSignAnalysis.cpp | 12 +- .../IfdsIde/Problems/IFDSSolverTest.cpp | 10 +- .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 22 +- .../IfdsIde/Problems/IFDSTypeAnalysis.cpp | 2 +- .../Problems/IFDSUninitializedVariables.cpp | 72 +- 35 files changed, 655 insertions(+), 669 deletions(-) diff --git a/include/phasar/DataFlow/IfdsIde/FlowFunctions.h b/include/phasar/DataFlow/IfdsIde/FlowFunctions.h index dda69748e0..87a3db452e 100644 --- a/include/phasar/DataFlow/IfdsIde/FlowFunctions.h +++ b/include/phasar/DataFlow/IfdsIde/FlowFunctions.h @@ -97,533 +97,529 @@ using FlowFunctionPtrTypeOf = std::shared_ptr; template > using FlowFunctionPtrType = FlowFunctionPtrTypeOf>; -/// A flow function that propagates all incoming facts unchanged. -/// -/// Given a flow-function f = identityFlow(), then for all incoming -/// dataflow-facts x, f(x) = {x}. -/// -/// In the exploded supergraph it may look as follows: -/// -/// x1 x1 x3 ... -/// | | | ... -/// id-instruction | | | ... -/// v v v ... -/// x1 x2 x3 ... -/// -template > auto identityFlow() { - struct IdFF final : public FlowFunction { - Container computeTargets(D Source) override { return {std::move(Source)}; } - }; - static auto TheIdentity = std::make_shared(); - - return TheIdentity; -} +/// Wrapper flow function that is automatically used by the IDESolver if the +/// autoAddZero configuration option is set to true (default). +/// Ensures that the tautological zero-flow fact (Λ) does not get killed. +template > +class ZeroedFlowFunction : public FlowFunction { + using typename FlowFunction::container_type; + using typename FlowFunction::FlowFunctionPtrType; -/// The most generic flow function. Invokes the passed function object F to -/// retrieve the desired data-flows. -/// -/// So, given a flow function f = lambdaFlow(F), then for all incoming -/// dataflow-facts x, f(x) = F(x). -/// -/// In the exploded supergraph it may look as follows: -/// -/// x -/// | -/// inst F -/// / / | \ \ ... -/// v v v v v -/// x1 x2 x x3 x4 -/// -template auto lambdaFlow(Fn &&F) { - using Container = std::invoke_result_t; - struct LambdaFlow final : public FlowFunction { - LambdaFlow(Fn &&F) : Flow(std::forward(F)) {} - Container computeTargets(D Source) override { - return std::invoke(Flow, std::move(Source)); +public: + ZeroedFlowFunction(FlowFunctionPtrType FF, D ZV) + : Delegate(std::move(FF)), ZeroValue(ZV) {} + container_type computeTargets(D Source) override { + if (Source == ZeroValue) { + container_type Result = Delegate->computeTargets(Source); + Result.insert(ZeroValue); + return Result; } + return Delegate->computeTargets(Source); + } - [[no_unique_address]] std::decay_t Flow; - }; +private: + FlowFunctionPtrType Delegate; + D ZeroValue; +}; - return std::make_shared(std::forward(F)); -} +namespace detail { +template +Container makeContainer(Range &&Rng) { + if constexpr (std::is_convertible_v, Container>) { + return std::forward(Rng); + } else { + Container C; + reserveIfPossible(C, Rng.size()); + for (auto &&Fact : Rng) { + C.insert(std::forward(Fact)); + } + return C; + } +}; +} // namespace detail //===----------------------------------------------------------------------===// -// Gen flow functions +// Flow Function Templates +//===----------------------------------------------------------------------===// -/// A flow function that generates a new dataflow fact (FactToGenerate) if -/// called with an already known dataflow fact (From). All other facts are -/// propagated like with the identityFlow. -/// -/// Given a flow function f = generateFlow(v, w), then for all incoming dataflow -/// facts x: -/// f(w) = {v, w}, -/// f(x) = {x}. -/// -/// In the exploded supergraph it may look as follows: -/// -/// x w u ... -/// | |\ | ... -/// inst | | \ | ... -/// v v v v ... -/// x w v u -/// -/// \note If the FactToGenerate already holds at the beginning of the statement, -/// this flow function does not kill it. For IFDS analysis it makes no -/// difference, but in the case of IDE, the corresponding edge functions are -/// being joined together potentially lowing precition. If that is an issue, use -/// transferFlow instead. -template > -auto generateFlow(psr::type_identity_t FactToGenerate, D From) { - struct GenFrom final : public FlowFunction { - GenFrom(D GenValue, D FromValue) - : GenValue(std::move(GenValue)), FromValue(std::move(FromValue)) {} - - Container computeTargets(D Source) override { - if (Source == FromValue) { - return {std::move(Source), GenValue}; - } - return {std::move(Source)}; - } +template class FlowFunctionTemplates { +public: + using d_t = D; + using container_type = Container; - D GenValue; - D FromValue; - }; + /// A flow function that propagates all incoming facts unchanged. + /// + /// Given a flow-function f = identityFlow(), then for all incoming + /// dataflow-facts x, f(x) = {x}. + /// + /// In the exploded supergraph it may look as follows: + /// + /// x1 x1 x3 ... + /// | | | ... + /// id-instruction | | | ... + /// v v v ... + /// x1 x2 x3 ... + /// + static auto identityFlow() { + struct IdFF final : public FlowFunction { + container_type computeTargets(d_t Source) override { + return {std::move(Source)}; + } + }; + static auto TheIdentity = std::make_shared(); - return std::make_shared(std::move(FactToGenerate), std::move(From)); -} + return TheIdentity; + } -/// A flow function similar to generateFlow, that generates a new dataflow fact -/// (FactToGenerate), if the given Predicate evaluates to true on an incoming -/// dataflow fact -/// -/// So, given a flow function f = generateFlowIf(v, p), for all incoming -/// dataflow facts x: -/// f(x) = {v, x} if p(x) == true -/// f(x) = {x} else. -/// -template , - typename Fn = psr::TrueFn, - typename = std::enable_if_t>> -auto generateFlowIf(D FactToGenerate, Fn Predicate) { - struct GenFlowIf final : public FlowFunction { - GenFlowIf(D GenValue, Fn &&Predicate) - : GenValue(std::move(GenValue)), - Predicate(std::forward(Predicate)) {} - - Container computeTargets(D Source) override { - if (std::invoke(Predicate, Source)) { - return {std::move(Source), GenValue}; + /// The most generic flow function. Invokes the passed function object F to + /// retrieve the desired data-flows. + /// + /// So, given a flow function f = lambdaFlow(F), then for all incoming + /// dataflow-facts x, f(x) = F(x). + /// + /// In the exploded supergraph it may look as follows: + /// + /// x + /// | + /// inst F + /// / / | \ \ ... + /// v v v v v + /// x1 x2 x x3 x4 + /// + template static auto lambdaFlow(Fn &&F) { + struct LambdaFlow final : public FlowFunction { + LambdaFlow(Fn &&F) : Flow(std::forward(F)) {} + container_type computeTargets(d_t Source) override { + return std::invoke(Flow, std::move(Source)); } - return {std::move(Source)}; - } - D GenValue; - [[no_unique_address]] std::decay_t Predicate; - }; + [[no_unique_address]] std::decay_t Flow; + }; - return std::make_shared(std::move(FactToGenerate), - std::forward(Predicate)); -} + return std::make_shared(std::forward(F)); + } -/// A flow function that generates multiple new dataflow facts (FactsToGenerate) -/// if called from an already known dataflow fact (From). -/// -/// Given a flow function f = generateManyFlows({v1, v2, ..., vN}, w), for all -/// incoming dataflow facts x: -/// f(w) = {v1, v2, ..., vN, w} -/// f(x) = {x}. -/// -/// In the exploded supergraph it may look as follows: -/// -/// x w u ... -/// | |\ \ ... \ | ... -/// inst | | \ \ ... \ | ... -/// v v v v ... \ v ... -/// x w v1 v2 ... vN u -/// -template , - typename Range = std::initializer_list, - typename = std::enable_if_t>> -auto generateManyFlows(Range &&FactsToGenerate, D From) { - struct GenMany final : public FlowFunction { - GenMany(Container &&GenValues, D FromValue) - : GenValues(std::move(GenValues)), FromValue(std::move(FromValue)) {} - - Container computeTargets(D Source) override { - if (Source == FromValue) { - auto Ret = GenValues; - Ret.insert(std::move(Source)); - return Ret; + //===----------------------------------------------------------------------===// + // Gen flow functions + + /// A flow function that generates a new dataflow fact (FactToGenerate) if + /// called with an already known dataflow fact (From). All other facts are + /// propagated like with the identityFlow. + /// + /// Given a flow function f = generateFlow(v, w), then for all incoming + /// dataflow facts x: + /// f(w) = {v, w}, + /// f(x) = {x}. + /// + /// In the exploded supergraph it may look as follows: + /// + /// x w u ... + /// | |\ | ... + /// inst | | \ | ... + /// v v v v ... + /// x w v u + /// + /// \note If the FactToGenerate already holds at the beginning of the + /// statement, this flow function does not kill it. For IFDS analysis it makes + /// no difference, but in the case of IDE, the corresponding edge functions + /// are being joined together potentially lowing precition. If that is an + /// issue, use transferFlow instead. + static auto generateFlow(d_t FactToGenerate, d_t From) { + struct GenFrom final : public FlowFunction { + GenFrom(d_t GenValue, d_t FromValue) + : GenValue(std::move(GenValue)), FromValue(std::move(FromValue)) {} + + container_type computeTargets(d_t Source) override { + if (Source == FromValue) { + return {std::move(Source), GenValue}; + } + return {std::move(Source)}; } - return {std::move(Source)}; - } - Container GenValues; - D FromValue; - }; - - auto MakeContainer = [](Range &&Rng) -> Container { - if constexpr (std::is_convertible_v, Container>) { - return std::forward(Rng); - } else { - Container C; - for (auto &&Fact : Rng) { - C.insert(std::forward(Fact)); - } - return C; - } - }; - return std::make_shared( - MakeContainer(std::forward(FactsToGenerate)), std::move(From)); -} + d_t GenValue; + d_t FromValue; + }; -//===----------------------------------------------------------------------===// -// Kill flow functions + return std::make_shared(std::move(FactToGenerate), + std::move(From)); + } -/// A flow function that stops propagating a specific dataflow fact -/// (FactToKill). -/// -/// Given a flow function f = killFlow(v), for all incoming dataflow facts x: -/// f(v) = {} -/// f(x) = {x} -/// -/// In the exploded supergraph it may look as follows: -/// -/// u v w ... -/// | | | -/// inst | | -/// v v -/// u v w ... -/// -template > -auto killFlow(D FactToKill) { - struct KillFlow final : public FlowFunction { - KillFlow(D KillValue) : KillValue(std::move(KillValue)) {} - Container computeTargets(D Source) override { - if (Source == KillValue) { - return {}; + /// A flow function similar to generateFlow, that generates a new dataflow + /// fact (FactToGenerate), if the given Predicate evaluates to true on an + /// incoming dataflow fact + /// + /// So, given a flow function f = generateFlowIf(v, p), for all incoming + /// dataflow facts x: + /// f(x) = {v, x} if p(x) == true + /// f(x) = {x} else. + /// + template >> + static auto generateFlowIf(d_t FactToGenerate, Fn Predicate) { + struct GenFlowIf final : public FlowFunction { + GenFlowIf(d_t GenValue, Fn &&Predicate) + : GenValue(std::move(GenValue)), + Predicate(std::forward(Predicate)) {} + + container_type computeTargets(d_t Source) override { + if (std::invoke(Predicate, Source)) { + return {std::move(Source), GenValue}; + } + return {std::move(Source)}; } - return {std::move(Source)}; - } - D KillValue; - }; - return std::make_shared(std::move(FactToKill)); -} + d_t GenValue; + [[no_unique_address]] std::decay_t Predicate; + }; -/// A flow function similar to killFlow that stops propagating all dataflow -/// facts for that the given Predicate evaluates to true. -/// -/// Given a flow function f = killFlowIf(p), for all incoming dataflow facts x: -/// f(x) = {} if p(x) == true -/// f(x) = {x} else. -/// -template , - typename Fn = psr::TrueFn, - typename = std::enable_if_t>> -auto killFlowIf(Fn Predicate) { - struct KillFlowIf final : public FlowFunction { - KillFlowIf(Fn &&Predicate) : Predicate(std::forward(Predicate)) {} - - Container computeTargets(D Source) override { - if (std::invoke(Predicate, Source)) { - return {}; + return std::make_shared(std::move(FactToGenerate), + std::forward(Predicate)); + } + + /// A flow function that generates multiple new dataflow facts + /// (FactsToGenerate) if called from an already known dataflow fact (From). + /// + /// Given a flow function f = generateManyFlows({v1, v2, ..., vN}, w), for all + /// incoming dataflow facts x: + /// f(w) = {v1, v2, ..., vN, w} + /// f(x) = {x}. + /// + /// In the exploded supergraph it may look as follows: + /// + /// x w u ... + /// | |\ \ ... \ | ... + /// inst | | \ \ ... \ | ... + /// v v v v ... \ v ... + /// x w v1 v2 ... vN u + /// + template , + typename = std::enable_if_t>> + static auto generateManyFlows(Range &&FactsToGenerate, d_t From) { + struct GenMany final : public FlowFunction { + GenMany(container_type &&GenValues, d_t FromValue) + : GenValues(std::move(GenValues)), FromValue(std::move(FromValue)) {} + + container_type computeTargets(d_t Source) override { + if (Source == FromValue) { + auto Ret = GenValues; + Ret.insert(std::move(Source)); + return Ret; + } + return {std::move(Source)}; } - return {std::move(Source)}; - } - [[no_unique_address]] std::decay_t Predicate; - }; + container_type GenValues; + d_t FromValue; + }; - return std::make_shared(std::forward(Predicate)); -} + return std::make_shared(detail::makeContainer( + std::forward(FactsToGenerate)), + std::move(From)); + } -/// A flow function that stops propagating a specific set of dataflow facts -/// (FactsToKill). -/// -/// Given a flow function f = killManyFlows({v1, v2, ..., vN}), for all incoming -/// dataflow facts x: -/// f(v1) = {} -/// f(v2) = {} -/// ... -/// f(vN) = {} -/// f(x) = {x}. -/// -/// In the exploded supergraph it may look as follows: -/// -/// u v1 v2 ... vN w ... -/// | | | | | -/// inst | | -/// v v -/// u v1 v2 ... vN w ... -/// -template , - typename Range = std::initializer_list, - typename = std::enable_if_t>> -auto killManyFlows(Range &&FactsToKill) { - struct KillMany final : public FlowFunction { - KillMany(Container &&KillValues) : KillValues(std::move(KillValues)) {} - - Container computeTargets(D Source) override { - if (KillValues.count(Source)) { - return {}; + //===----------------------------------------------------------------------===// + // Kill flow functions + + /// A flow function that stops propagating a specific dataflow fact + /// (FactToKill). + /// + /// Given a flow function f = killFlow(v), for all incoming dataflow facts x: + /// f(v) = {} + /// f(x) = {x} + /// + /// In the exploded supergraph it may look as follows: + /// + /// u v w ... + /// | | | + /// inst | | + /// v v + /// u v w ... + /// + static auto killFlow(d_t FactToKill) { + struct KillFlow final : public FlowFunction { + KillFlow(d_t KillValue) : KillValue(std::move(KillValue)) {} + container_type computeTargets(d_t Source) override { + if (Source == KillValue) { + return {}; + } + return {std::move(Source)}; } - return {std::move(Source)}; - } + d_t KillValue; + }; - Container KillValues; - }; + return std::make_shared(std::move(FactToKill)); + } - auto MakeContainer = [](Range &&Rng) -> Container { - if constexpr (std::is_convertible_v, Container>) { - return std::forward(Rng); - } else { - Container C; - for (auto &&Fact : Rng) { - C.insert(std::forward(Fact)); + /// A flow function similar to killFlow that stops propagating all dataflow + /// facts for that the given Predicate evaluates to true. + /// + /// Given a flow function f = killFlowIf(p), for all incoming dataflow facts + /// x: + /// f(x) = {} if p(x) == true + /// f(x) = {x} else. + /// + template >> + static auto killFlowIf(Fn Predicate) { + struct KillFlowIf final : public FlowFunction { + KillFlowIf(Fn &&Predicate) : Predicate(std::forward(Predicate)) {} + + container_type computeTargets(d_t Source) override { + if (std::invoke(Predicate, Source)) { + return {}; + } + return {std::move(Source)}; } - return C; - } - }; - return std::make_shared( - MakeContainer(std::forward(FactsToKill))); -} -/// A flow function that stops propagating *all* incoming dataflow facts. -/// -/// Given a flow function f = killAllFlows(), for all incoming dataflow facts x, -/// f(x) = {}. -/// -template > auto killAllFlows() { - struct KillAllFF final : public FlowFunction { - Container computeTargets(D Source) override { return {std::move(Source)}; } - }; - static auto TheKillAllFlow = std::make_shared(); + [[no_unique_address]] std::decay_t Predicate; + }; - return TheKillAllFlow; -} - -//===----------------------------------------------------------------------===// -// Gen-and-kill flow functions + return std::make_shared(std::forward(Predicate)); + } -/// A flow function that composes kill and generate flow functions. -/// Like generateFlow it generates a new dataflow fact (FactToGenerate), if -/// called with a specific dataflow fact (From). -/// However, like killFlowIf it stops propagating all other dataflow facts. -/// -/// Given a flow function f = generateFlowAndKillAllOthers(v, w), for all -/// incoming dataflow facts x: -/// f(w) = {v, w} -/// f(x) = {}. -/// -/// Equivalent to: killFlowIf(λz.z!=w) o generateFlow(v, w) (where o denotes -/// function composition) -/// -/// In the exploded supergraph it may look as follows: -/// -/// x w u ... -/// | |\ | -/// inst | \ ... -/// v v -/// x w v u -/// -template > -auto generateFlowAndKillAllOthers(psr::type_identity_t FactToGenerate, - D From) { - struct GenFlowAndKillAllOthers final : public FlowFunction { - GenFlowAndKillAllOthers(D GenValue, D FromValue) - : GenValue(std::move(GenValue)), FromValue(std::move(FromValue)) {} - - Container computeTargets(D Source) override { - if (Source == FromValue) { - return {std::move(Source), GenValue}; + /// A flow function that stops propagating a specific set of dataflow facts + /// (FactsToKill). + /// + /// Given a flow function f = killManyFlows({v1, v2, ..., vN}), for all + /// incoming dataflow facts x: + /// f(v1) = {} + /// f(v2) = {} + /// ... + /// f(vN) = {} + /// f(x) = {x}. + /// + /// In the exploded supergraph it may look as follows: + /// + /// u v1 v2 ... vN w ... + /// | | | | | + /// inst | | + /// v v + /// u v1 v2 ... vN w ... + /// + template , + typename = std::enable_if_t>> + static auto killManyFlows(Range &&FactsToKill) { + struct KillMany final : public FlowFunction { + KillMany(Container &&KillValues) : KillValues(std::move(KillValues)) {} + + container_type computeTargets(d_t Source) override { + if (KillValues.count(Source)) { + return {}; + } + return {std::move(Source)}; } - return {}; - } - D GenValue; - D FromValue; - }; + container_type KillValues; + }; - return std::make_shared(std::move(FactToGenerate), - std::move(From)); -} + return std::make_shared(detail::makeContainer( + std::forward(FactsToKill))); + } -/// A flow function similar to generateFlowAndKillAllOthers that may generate -/// multiple dataflow facts (FactsToGenerate) is called with a specific fact -/// (From) and stops propagating all other dataflow facts. -/// -/// Given a flow function f = generateManyFlowsAndKillAllOthers({v1, v2, ..., -/// vN}, w), for all incoming dataflow facts x: -/// f(w) = {v1, v2, ..., vN, w} -/// f(x) = {}. -/// -/// In the exploded supergraph it may look as follows: -/// -/// x w u ... -/// | |\ \ ... \ | ... -/// inst | \ \ ... \ ... -/// v v v ... \ ... -/// x w v1 v2 ... vN u -/// -template , - typename Range = std::initializer_list, - typename = std::enable_if_t>> -auto generateManyFlowsAndKillAllOthers(Range &&FactsToGenerate, D From) { - struct GenManyAndKillAllOthers final : public FlowFunction { - GenManyAndKillAllOthers(Container &&GenValues, D FromValue) - : GenValues(std::move(GenValues)), FromValue(std::move(FromValue)) {} - - Container computeTargets(D Source) override { - if (Source == FromValue) { - auto Ret = GenValues; - Ret.insert(std::move(Source)); - return Ret; + /// A flow function that stops propagating *all* incoming dataflow facts. + /// + /// Given a flow function f = killAllFlows(), for all incoming dataflow facts + /// x, f(x) = {}. + /// + static auto killAllFlows() { + struct KillAllFF final : public FlowFunction { + Container computeTargets(d_t Source) override { + return {std::move(Source)}; } - return {}; - } + }; + static auto TheKillAllFlow = std::make_shared(); + + return TheKillAllFlow; + } - Container GenValues; - D FromValue; - }; - - auto MakeContainer = [](Range &&Rng) -> Container { - if constexpr (std::is_convertible_v, Container>) { - return std::forward(Rng); - } else { - Container C; - for (auto &&Fact : Rng) { - C.insert(std::forward(Fact)); + //===----------------------------------------------------------------------===// + // Gen-and-kill flow functions + + /// A flow function that composes kill and generate flow functions. + /// Like generateFlow it generates a new dataflow fact (FactToGenerate), if + /// called with a specific dataflow fact (From). + /// However, like killFlowIf it stops propagating all other dataflow facts. + /// + /// Given a flow function f = generateFlowAndKillAllOthers(v, w), for all + /// incoming dataflow facts x: + /// f(w) = {v, w} + /// f(x) = {}. + /// + /// Equivalent to: killFlowIf(λz.z!=w) o generateFlow(v, w) (where o denotes + /// function composition) + /// + /// In the exploded supergraph it may look as follows: + /// + /// x w u ... + /// | |\ | + /// inst | \ ... + /// v v + /// x w v u + /// + static auto generateFlowAndKillAllOthers(d_t FactToGenerate, d_t From) { + struct GenFlowAndKillAllOthers final + : public FlowFunction { + GenFlowAndKillAllOthers(d_t GenValue, d_t FromValue) + : GenValue(std::move(GenValue)), FromValue(std::move(FromValue)) {} + + container_type computeTargets(d_t Source) override { + if (Source == FromValue) { + return {std::move(Source), GenValue}; + } + return {}; } - return C; - } - }; - return std::make_shared( - MakeContainer(std::forward(FactsToGenerate)), std::move(From)); -} -//===----------------------------------------------------------------------===// -// Miscellaneous flow functions + d_t GenValue; + d_t FromValue; + }; -/// A flow function that, similar to generateFlow, generates a new dataflow fact -/// (FactsToGenerate) when called with a specific dataflow fact (From). -/// Unlike generateFlow, it kills FactToGenerate if it is part of the incoming -/// facts. THis has no additional effect for IFDS analyses (which in fact should -/// use generateFlow instead), but for IDE analyses it may avoid joining the -/// edge functions reaching the FactToGenerate together which may improve the -/// analysis' precision. -/// -/// Given a flow function f = transferFlow(v, w), for all incoming dataflow -/// facts x: -/// f(v) = {} -/// f(w) = {v, w} -/// f(x) = {x}. -/// -/// In the exploded supergraph it may look as follows: -/// -/// x w v u ... -/// | |\ | | ... -/// | | \ | ... -/// inst | | \ | ... -/// v v v v ... -/// x w v u -/// -template > -auto transferFlow(psr::type_identity_t FactToGenerate, D From) { - struct TransferFlow final : public FlowFunction { - TransferFlow(D GenValue, D FromValue) - : GenValue(std::move(GenValue)), FromValue(std::move(FromValue)) {} - - Container computeTargets(D Source) override { - if (Source == FromValue) { - return {std::move(Source), GenValue}; - } - if (Source == GenValue) { + return std::make_shared(std::move(FactToGenerate), + std::move(From)); + } + + /// A flow function similar to generateFlowAndKillAllOthers that may generate + /// multiple dataflow facts (FactsToGenerate) is called with a specific fact + /// (From) and stops propagating all other dataflow facts. + /// + /// Given a flow function f = generateManyFlowsAndKillAllOthers({v1, v2, ..., + /// vN}, w), for all incoming dataflow facts x: + /// f(w) = {v1, v2, ..., vN, w} + /// f(x) = {}. + /// + /// In the exploded supergraph it may look as follows: + /// + /// x w u ... + /// | |\ \ ... \ | ... + /// inst | \ \ ... \ ... + /// v v v ... \ ... + /// x w v1 v2 ... vN u + /// + template , + typename = std::enable_if_t>> + static auto generateManyFlowsAndKillAllOthers(Range &&FactsToGenerate, + d_t From) { + struct GenManyAndKillAllOthers final + : public FlowFunction { + GenManyAndKillAllOthers(Container &&GenValues, d_t FromValue) + : GenValues(std::move(GenValues)), FromValue(std::move(FromValue)) {} + + container_type computeTargets(d_t Source) override { + if (Source == FromValue) { + auto Ret = GenValues; + Ret.insert(std::move(Source)); + return Ret; + } return {}; } - return {std::move(Source)}; - } - D GenValue; - D FromValue; - }; + container_type GenValues; + d_t FromValue; + }; - return std::make_shared(std::move(FactToGenerate), - std::move(From)); -} + return std::make_shared( + detail::makeContainer( + std::forward(FactsToGenerate)), + std::move(From)); + } -/// A flow function that takes two other flow functions OneFF and OtherFF and -/// applies both flow functions on each input merging the results together with -/// set-union. -/// -/// Given a flow function f = unionFlows(g, h), for all incoming dataflow facts -/// x: -/// f(x) = g(x) u h(x). (where u denotes set-union) -/// -template && - std::is_same_v>> -auto unionFlows(FlowFunctionPtrTypeOf OneFF, - FlowFunctionPtrTypeOf OtherFF) { - struct UnionFlow final : public FlowFunction { - UnionFlow(FlowFunctionPtrTypeOf OneFF, - FlowFunctionPtrTypeOf OtherFF) noexcept - : OneFF(std::move(OneFF)), OtherFF(std::move(OtherFF)) {} - - Container computeTargets(D Source) override { - auto OneRet = OneFF->computeTargets(Source); - auto OtherRet = OtherFF->computeTargets(std::move(Source)); - if (OneRet.size() < OtherRet.size()) { - std::swap(OneRet, OtherRet); + //===----------------------------------------------------------------------===// + // Miscellaneous flow functions + + /// A flow function that, similar to generateFlow, generates a new dataflow + /// fact (FactsToGenerate) when called with a specific dataflow fact (From). + /// Unlike generateFlow, it kills FactToGenerate if it is part of the incoming + /// facts. THis has no additional effect for IFDS analyses (which in fact + /// should use generateFlow instead), but for IDE analyses it may avoid + /// joining the edge functions reaching the FactToGenerate together which may + /// improve the analysis' precision. + /// + /// Given a flow function f = transferFlow(v, w), for all incoming dataflow + /// facts x: + /// f(v) = {} + /// f(w) = {v, w} + /// f(x) = {x}. + /// + /// In the exploded supergraph it may look as follows: + /// + /// x w v u ... + /// | |\ | | ... + /// | | \ | ... + /// inst | | \ | ... + /// v v v v ... + /// x w v u + /// + static auto transferFlow(d_t FactToGenerate, d_t From) { + struct TransferFlow final : public FlowFunction { + TransferFlow(d_t GenValue, d_t FromValue) + : GenValue(std::move(GenValue)), FromValue(std::move(FromValue)) {} + + container_type computeTargets(d_t Source) override { + if (Source == FromValue) { + return {std::move(Source), GenValue}; + } + if (Source == GenValue) { + return {}; + } + return {std::move(Source)}; } - OneRet.insert(std::make_move_iterator(OtherRet.begin()), - std::make_move_iterator(OtherRet.end())); - return OneRet; - } + d_t GenValue; + d_t FromValue; + }; - FlowFunctionPtrTypeOf OneFF; - FlowFunctionPtrTypeOf OtherFF; - }; + return std::make_shared(std::move(FactToGenerate), + std::move(From)); + } - return std::make_shared(std::move(OneFF), std::move(OtherFF)); -} + /// A flow function that takes two other flow functions OneFF and OtherFF and + /// applies both flow functions on each input merging the results together + /// with set-union. + /// + /// Given a flow function f = unionFlows(g, h), for all incoming dataflow + /// facts x: + /// f(x) = g(x) u h(x). (where u denotes set-union) + /// + template && + std::is_same_v && + std::is_same_v>> + auto unionFlows(FlowFunctionPtrTypeOf OneFF, + FlowFunctionPtrTypeOf OtherFF) { + struct UnionFlow final : public FlowFunction { + UnionFlow(FlowFunctionPtrTypeOf OneFF, + FlowFunctionPtrTypeOf OtherFF) noexcept + : OneFF(std::move(OneFF)), OtherFF(std::move(OtherFF)) {} + + container_type computeTargets(d_t Source) override { + auto OneRet = OneFF->computeTargets(Source); + auto OtherRet = OtherFF->computeTargets(std::move(Source)); + if (OneRet.size() < OtherRet.size()) { + std::swap(OneRet, OtherRet); + } + + OneRet.insert(std::make_move_iterator(OtherRet.begin()), + std::make_move_iterator(OtherRet.end())); + return OneRet; + } -/// Wrapper flow function that is automatically used by the IDESolver if the -/// autoAddZero configuration option is set to true (default). -/// Ensures that the tautological zero-flow fact (Λ) does not get killed. -template > -class ZeroedFlowFunction : public FlowFunction { - using typename FlowFunction::container_type; - using typename FlowFunction::FlowFunctionPtrType; + FlowFunctionPtrTypeOf OneFF; + FlowFunctionPtrTypeOf OtherFF; + }; -public: - ZeroedFlowFunction(FlowFunctionPtrType FF, D ZV) - : Delegate(std::move(FF)), ZeroValue(ZV) {} - container_type computeTargets(D Source) override { - if (Source == ZeroValue) { - container_type Result = Delegate->computeTargets(Source); - Result.insert(ZeroValue); - return Result; - } - return Delegate->computeTargets(Source); + return std::make_shared(std::move(OneFF), std::move(OtherFF)); } - -private: - FlowFunctionPtrType Delegate; - D ZeroValue; }; //===----------------------------------------------------------------------===// // FlowFunctions Class //===----------------------------------------------------------------------===// -template > -class FlowFunctions { +template +class FlowFunctions + : protected FlowFunctionTemplates { static_assert( std::is_same::value, @@ -858,7 +854,8 @@ class FlowFunctions { // The default implementation returns a nullptr to indicate that the mechanism // should not be used. // - virtual FlowFunctionPtrType getSummaryFlowFunction(n_t Curr, f_t CalleeFun) { + virtual FlowFunctionPtrType getSummaryFlowFunction(n_t /*Curr*/, + f_t /*CalleeFun*/) { return nullptr; } }; @@ -868,7 +865,8 @@ class FlowFunctions { //////////////////////////////////////////////////////////////////////////////// template > -class Identity : public FlowFunction { +class [[deprecated("Use identityFlow() instead")]] Identity + : public FlowFunction { public: using typename FlowFunction::FlowFunctionType; using typename FlowFunction::FlowFunctionPtrType; @@ -913,7 +911,7 @@ typename FlowFunction::FlowFunctionPtrType makeLambdaFlow(Fn &&F) { } template > -class Compose : public FlowFunction { +class [[deprecated]] Compose : public FlowFunction { public: using typename FlowFunction::FlowFunctionType; using typename FlowFunction::FlowFunctionPtrType; diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index 3d2bde9e60..0f373bc14b 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -77,9 +77,10 @@ class IDETabulationProblem : public FlowFunctions, using ConfigurationTy = HasNoConfigurationType; - explicit IDETabulationProblem(const ProjectIRDBBase *IRDB, - std::vector EntryPoints, - std::optional ZeroValue) + explicit IDETabulationProblem( + const ProjectIRDBBase *IRDB, std::vector EntryPoints, + std::optional + ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IRDB(IRDB), EntryPoints(std::move(EntryPoints)), ZeroValue(std::move(ZeroValue)) { assert(IRDB != nullptr); @@ -89,7 +90,7 @@ class IDETabulationProblem : public FlowFunctions, /// Checks if the given data-flow fact is the special tautological lambda (or /// zero) fact. - [[nodiscard]] virtual bool isZeroValue(d_t FlowFact) const { + [[nodiscard]] virtual bool isZeroValue(d_t FlowFact) const noexcept { assert(ZeroValue.has_value()); return FlowFact == *ZeroValue; } @@ -99,7 +100,7 @@ class IDETabulationProblem : public FlowFunctions, [[nodiscard]] virtual InitialSeeds initialSeeds() = 0; /// Returns the special tautological lambda (or zero) fact. - [[nodiscard]] d_t getZeroValue() const { + [[nodiscard]] ByConstRef getZeroValue() const { assert(ZeroValue.has_value()); return *ZeroValue; } @@ -143,7 +144,8 @@ class IDETabulationProblem : public FlowFunctions, protected: typename FlowFunctions::FlowFunctionPtrType generateFromZero(d_t FactToGenerate) { - return generateFlow(std::move(FactToGenerate), getZeroValue()); + return FlowFunctions::generateFlow( + std::move(FactToGenerate), getZeroValue()); } /// Seeds that just start with ZeroValue and bottomElement() at the starting diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h index 57bff2b656..dba21e5d55 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h @@ -355,27 +355,6 @@ mapFactsToCaller(const llvm::CallBase *CallSite, PropagateZeroToCaller); } -//===----------------------------------------------------------------------===// -// Propagation flow functions - -/// Utility function to simplify writing a flow function of the form: -/// generateFlow(Load, from: Load->getPointerOperand()). -template > -FlowFunctionPtrType -propagateLoad(const llvm::LoadInst *Load) { - return generateFlow( - Load, Load->getPointerOperand()); -} - -/// Utility function to simplify writing a flow function of the form: -/// generateFlow(Store->getValueOperand(), from: Store->getPointerOperand()). -template > -FlowFunctionPtrType -propagateStore(const llvm::StoreInst *Store) { - return generateFlow( - Store->getValueOperand(), Store->getPointerOperand()); -} - //===----------------------------------------------------------------------===// // Update flow functions diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h index e0f6d8b9ed..ad55a98402 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h @@ -53,7 +53,7 @@ class LLVMZeroValue : public llvm::GlobalVariable { static const LLVMZeroValue *getInstance(); // NOLINTNEXTLINE(readability-identifier-naming) - static constexpr auto isLLVMZeroValue = [](const llvm::Value *V) { + static constexpr auto isLLVMZeroValue = [](const llvm::Value *V) noexcept { return V == getInstance(); }; }; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h index bcbf03137f..6aa8e7d11b 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h @@ -246,7 +246,7 @@ class IDEExtendedTaintAnalysis [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; // Printing functions diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h index 26ea81ca73..2be5e7f2d8 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h @@ -74,7 +74,7 @@ class IDEGeneralizedLCA : public IDETabulationProblem { [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; // in addition provide specifications for the IDE parts diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index 2354050421..e9ea1e2156 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -270,7 +270,7 @@ class IDEInstInteractionAnalysisT // if (const auto *Alloca = llvm::dyn_cast(Curr)) { PHASAR_LOG_LEVEL(DFADEBUG, "AllocaInst"); - return generateFromZero(Alloca); + return this->generateFromZero(Alloca); } // Handle indirect taints, i. e., propagate values that depend on branch @@ -293,7 +293,7 @@ class IDEInstInteractionAnalysisT // v v v v // 0 c x I // - return lambdaFlow([Br](d_t Src) { + return this->lambdaFlow([Br](d_t Src) { container_type Facts; Facts.insert(Src); if (Src == Br->getCondition()) { @@ -329,7 +329,7 @@ class IDEInstInteractionAnalysisT // v v v // 0 Y x // - return generateFlowIf( + return this->generateFlowIf( Load, [PointerOp = Load->getPointerOperand(), PTS = PT.getReachableAllocationSites( Load->getPointerOperand(), OnlyConsiderLocalAliases)]( @@ -355,7 +355,7 @@ class IDEInstInteractionAnalysisT // v v v // 0 x Y // - return lambdaFlow( + return this->lambdaFlow( [Store, PointerPTS = PT.getReachableAllocationSites( Store->getPointerOperand(), OnlyConsiderLocalAliases, Store)](d_t Src) -> container_type { @@ -396,7 +396,7 @@ class IDEInstInteractionAnalysisT // 0 y x // if (const auto *Load = llvm::dyn_cast(Curr)) { - return generateFlow(Load, Load->getPointerOperand()); + return this->generateFlow(Load, Load->getPointerOperand()); } // Handle store instructions // @@ -409,7 +409,7 @@ class IDEInstInteractionAnalysisT // 0 x y // if (const auto *Store = llvm::dyn_cast(Curr)) { - return lambdaFlow([Store](d_t Src) -> container_type { + return this->lambdaFlow([Store](d_t Src) -> container_type { // Override old value, i.e., kill value that is written to and // generate from value that is stored. if (Store->getPointerOperand() == Src) { @@ -448,7 +448,7 @@ class IDEInstInteractionAnalysisT // v v v v // 0 x o p // - return lambdaFlow([Inst = Curr](d_t Src) { + return this->lambdaFlow([Inst = Curr](d_t Src) { container_type Facts; if (IDEInstInteractionAnalysisT::isZeroValueImpl(Src)) { // keep the zero flow fact @@ -483,11 +483,11 @@ class IDEInstInteractionAnalysisT f_t DestFun) override { if (this->ICF->isHeapAllocatingFunction(DestFun)) { // Kill add facts and model the effects in getCallToRetFlowFunction(). - return killAllFlows(); + return this->killAllFlows(); } if (DestFun->isDeclaration()) { // We don't have anything that we could analyze, kill all facts. - return killAllFlows(); + return this->killAllFlows(); } const auto *CS = llvm::cast(CallSite); @@ -509,9 +509,9 @@ class IDEInstInteractionAnalysisT auto SRetFormal = CS->hasStructRetAttr() ? DestFun->getArg(0) : nullptr; if (SRetFormal) { - return unionFlows( + return this->unionFlows( std::move(MapFactsToCalleeFF), - generateFlowAndKillAllOthers(SRetFormal, this->getZeroValue())); + this->generateFlowAndKillAllOthers(SRetFormal, this->getZeroValue())); } return MapFactsToCalleeFF; @@ -582,9 +582,9 @@ class IDEInstInteractionAnalysisT } } - return lambdaFlow([CallSite = llvm::cast(CallSite), - OnlyDecls, - AllVoidRetTys](d_t Source) -> container_type { + return this->lambdaFlow([CallSite = llvm::cast(CallSite), + OnlyDecls, + AllVoidRetTys](d_t Source) -> container_type { // There are a few things to consider, in case only declarations of // callee targets are available. if (OnlyDecls) { @@ -659,7 +659,9 @@ class IDEInstInteractionAnalysisT return LLVMZeroValue::getInstance(); } - inline bool isZeroValue(d_t d) const override { return isZeroValueImpl(d); } + inline bool isZeroValue(d_t d) const noexcept override { + return isZeroValueImpl(d); + } // In addition provide specifications for the IDE parts. diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h index 770ff03aa7..7187e5d1b8 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h @@ -94,7 +94,7 @@ class IDELinearConstantAnalysis [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; // in addition provide specifications for the IDE parts diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h index 9c25256fff..40254b0720 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h @@ -66,7 +66,7 @@ class IDEProtoAnalysis : public IDETabulationProblem { [[nodiscard]] d_t createZeroValue() const; - bool isZeroValue(d_t Fact) const override; + bool isZeroValue(d_t Fact) const noexcept override; // in addition provide specifications for the IDE parts diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h index 4dc6e1c5b6..05e4aad308 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h @@ -80,7 +80,7 @@ class IDESecureHeapPropagation [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h index cceb38a9db..494ddb8a5c 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h @@ -67,7 +67,7 @@ class IDESolverTest : public IDETabulationProblem { [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; // in addition provide specifications for the IDE parts diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index 9339ef91f8..fe57965bf7 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -78,7 +78,7 @@ class IDETypeStateAnalysis [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; // in addition provide specifications for the IDE parts diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h index 4f11609a43..ca503b29fa 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h @@ -142,7 +142,7 @@ class IFDSConstAnalysis */ [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h index 62dcd7eb55..853c04404c 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h @@ -81,7 +81,7 @@ class IFDSFieldSensTaintAnalysis return ExtendedValue(LLVMZeroValue::getInstance()); } - [[nodiscard]] bool isZeroValue(ExtendedValue EV) const override { + [[nodiscard]] bool isZeroValue(ExtendedValue EV) const noexcept override { return LLVMZeroValue::isLLVMZeroValue(EV.getValue()); } diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h index 16d7b1c59a..8cf494155a 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h @@ -52,7 +52,7 @@ class IFDSProtoAnalysis [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h index 67dae0c90d..a2e2ff1201 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h @@ -53,7 +53,7 @@ class IFDSSignAnalysis [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h index 25b7c28a53..178e8f0920 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h @@ -51,7 +51,7 @@ class IFDSSolverTest [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h index 9df7cf69b3..f02ebfb810 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h @@ -77,7 +77,7 @@ class IFDSTaintAnalysis [[nodiscard]] d_t createZeroValue() const; - bool isZeroValue(d_t FlowFact) const override; + bool isZeroValue(d_t FlowFact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Inst) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h index 9c4b55c9dc..1527bf3503 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h @@ -44,7 +44,7 @@ class IFDSTypeAnalysis [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h index 24e07c8ffd..597902ae6f 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h @@ -60,7 +60,7 @@ class IFDSUninitializedVariables [[nodiscard]] d_t createZeroValue() const; - [[nodiscard]] bool isZeroValue(d_t Fact) const override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; diff --git a/include/phasar/Utils/TypeTraits.h b/include/phasar/Utils/TypeTraits.h index 0957292bb8..04983a9a32 100644 --- a/include/phasar/Utils/TypeTraits.h +++ b/include/phasar/Utils/TypeTraits.h @@ -66,6 +66,12 @@ template struct has_str().str())> : std::true_type { }; // NOLINT +template struct has_reserve : std::false_type {}; +template +struct has_reserve< + T, std::void_t().reserve(size_t(0)))>> + : std::true_type {}; + template struct has_erase_iterator : std::false_type {}; // NOLINT template @@ -233,6 +239,12 @@ template struct DefaultConstruct { } }; +template void reserveIfPossible(T &Container, size_t Capacity) { + if constexpr (detail::has_reserve::value) { + Container.reserve(Capacity); + } +} + // NOLINTEND(readability-identifier-naming) } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index ca4846b5c9..2892959788 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -65,7 +65,7 @@ auto IDEExtendedTaintAnalysis::createZeroValue() const -> d_t { return FactFactory.getOrCreateZero(); } -bool IDEExtendedTaintAnalysis::isZeroValue(d_t Fact) const { +bool IDEExtendedTaintAnalysis::isZeroValue(d_t Fact) const noexcept { return Fact->isZero(); } @@ -95,7 +95,7 @@ IDEExtendedTaintAnalysis::getNormalFlowFunction(n_t Curr, } if (const auto *Phi = llvm::dyn_cast(Curr)) { - return lambdaFlow([this, Phi](d_t Source) -> std::set { + return lambdaFlow([this, Phi](d_t Source) -> std::set { auto NumOps = Phi->getNumIncomingValues(); for (unsigned I = 0; I < NumOps; ++I) { if (equivalent(Source, makeFlowFact(Phi->getIncomingValue(I)))) { @@ -107,7 +107,7 @@ IDEExtendedTaintAnalysis::getNormalFlowFunction(n_t Curr, }); } - return Identity::getInstance(); + return identityFlow(); } IDEExtendedTaintAnalysis::FlowFunctionPtrType @@ -122,8 +122,8 @@ IDEExtendedTaintAnalysis::getStoreFF(const llvm::Value *PointerOp, AliasInfoRef::AliasSetPtrTy PTS = nullptr; auto Mem = makeFlowFact(PointerOp); - return lambdaFlow([this, TV, Mem, PTS, PointerOp, ValueOp, Store, - PALevel](d_t Source) mutable -> std::set { + return lambdaFlow([this, TV, Mem, PTS, PointerOp, ValueOp, Store, + PALevel](d_t Source) mutable -> std::set { if (Source->isZero()) { std::set Ret = {Source}; generateFromZero(Ret, Store, PointerOp, ValueOp, @@ -267,8 +267,8 @@ auto IDEExtendedTaintAnalysis::handleConfig(const llvm::Instruction *Inst, populateWithMayAliases(SourceConfig); } - return lambdaFlow([Inst, this, SourceConfig{std::move(SourceConfig)}, - SinkConfig{std::move(SinkConfig)}](d_t Source) { + return lambdaFlow([Inst, this, SourceConfig{std::move(SourceConfig)}, + SinkConfig{std::move(SinkConfig)}](d_t Source) { std::set Ret = {Source}; if (Source->isZero()) { @@ -293,14 +293,13 @@ IDEExtendedTaintAnalysis::getCallFlowFunction(n_t CallStmt, f_t DestFun) { const auto *Call = llvm::cast(CallStmt); assert(Call); if (DestFun->isDeclaration()) { - return Identity::getInstance(); + return identityFlow(); } bool HasVarargs = Call->arg_size() > DestFun->arg_size(); const auto *const VA = HasVarargs ? getVAListTagOrNull(DestFun) : nullptr; - return lambdaFlow([this, Call, DestFun, - VA](d_t Source) -> std::set { + return lambdaFlow([this, Call, DestFun, VA](d_t Source) -> std::set { if (isZeroValue(Source)) { return {Source}; } @@ -388,7 +387,7 @@ IDEExtendedTaintAnalysis::getRetFlowFunction(n_t CallSite, f_t CalleeFun, if (!CallSite) { /// In case of unbalanced return, we may reach the artificial Global Ctor /// caller that has no caller - return killFlowIf([](d_t Source) { + return killFlowIf([](d_t Source) { return !llvm::isa_and_nonnull(Source->base()); }); } @@ -415,11 +414,11 @@ IDEExtendedTaintAnalysis::getRetFlowFunction(n_t CallSite, f_t CalleeFun, }; const auto *Call = llvm::cast(CallSite); - return lambdaFlow([this, Call, CalleeFun, - ExitStmt{llvm::cast(ExitStmt)}, - PTC{ArgAliasCache(PT, Call->arg_size(), - HasPreciseAliasInfo)}]( - d_t Source) mutable -> std::set { + return lambdaFlow([this, Call, CalleeFun, + ExitStmt{llvm::cast(ExitStmt)}, + PTC{ArgAliasCache(PT, Call->arg_size(), + HasPreciseAliasInfo)}]( + d_t Source) mutable -> std::set { if (isZeroValue(Source)) { return {Source}; } @@ -491,7 +490,7 @@ IDEExtendedTaintAnalysis::getCallToRetFlowFunction( // into // // that function - // return lambdaFlow([CallSite, this](d_t Source) -> std::set + // return lambdaFlow([CallSite, this](d_t Source) -> std::set // { // if (isZeroValue(Source)) { // return {}; @@ -532,7 +531,7 @@ IDEExtendedTaintAnalysis::getCallToRetFlowFunction( [](const llvm::Function *F) { return F->isDeclaration(); }); if (HasDeclaration) { - return Identity::getInstance(); + return identityFlow(); } return killFlow(getZeroValue()); diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp index a7656d23b0..ae742e9055 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp @@ -39,12 +39,6 @@ namespace psr { using namespace glca; -template >> -inline auto flow(Fn Func) { - return lambdaFlow(std::forward(Func)); -} - IDEGeneralizedLCA::IDEGeneralizedLCA(const LLVMProjectIRDB *IRDB, const LLVMBasedICFG *ICF, std::vector EntryPoints, @@ -63,9 +57,9 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, const auto *ValueOp = Store->getValueOperand(); if (isConstant(ValueOp)) { // llvm::outs() << "==> constant store" << std::endl; - return lambdaFlow([=](IDEGeneralizedLCA::d_t Source) - -> std::set { - // llvm::outs() << "##> normal lambdaFlow for: " << + return lambdaFlow([=](IDEGeneralizedLCA::d_t Source) + -> std::set { + // llvm::outs() << "##> normal lambdaFlow for: " << // llvmIRToString(curr) // << " with " << llvmIRToString(source) << std::endl; if (Source == PointerOp) { @@ -77,7 +71,7 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, return {Source}; }); } - return lambdaFlow( + return lambdaFlow( [=](IDEGeneralizedLCA::d_t Source) -> std::set { if (Source == PointerOp) { return {}; @@ -89,7 +83,7 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, }); } if (const auto *Load = llvm::dyn_cast(Curr)) { - return lambdaFlow( + return lambdaFlow( [=](IDEGeneralizedLCA::d_t Source) -> std::set { // llvm::outs() << "LOAD " << llvmIRToString(curr) << std::endl; // llvm::outs() << "\twith " << llvmIRToString(source) << " ==> "; @@ -102,7 +96,7 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, }); } if (const auto *Gep = llvm::dyn_cast(Curr)) { - return lambdaFlow( + return lambdaFlow( [=](IDEGeneralizedLCA::d_t Source) -> std::set { if (Source == Gep->getPointerOperand()) { return {Source, Gep}; @@ -116,7 +110,7 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, Cast->getSrcTy()->isFloatingPointTy()) && (Cast->getDestTy()->isIntegerTy() || Cast->getDestTy()->isFloatingPointTy())) { - return lambdaFlow( + return lambdaFlow( [=](IDEGeneralizedLCA::d_t Source) -> std::set { if (Source == Cast->getOperand(0)) { return {Source, Cast}; @@ -132,7 +126,7 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, bool BothConst = LeftConst && RightConst; bool NoneConst = !LeftConst && !RightConst; - return lambdaFlow( + return lambdaFlow( [=](IDEGeneralizedLCA::d_t Source) -> std::set { if (Source == Lhs || Source == Rhs || ((BothConst || NoneConst) && isZeroValue(Source))) { @@ -142,7 +136,7 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, }); } /*else if (llvm::isa(curr)) { auto op = curr->getOperand(0); - return lambdaFlow([=](IDEGeneralizedLCA::d_t source) + return lambdaFlow([=](IDEGeneralizedLCA::d_t source) -> std::set { if (source == op) return {source, curr}; @@ -151,7 +145,7 @@ IDEGeneralizedLCA::getNormalFlowFunction(IDEGeneralizedLCA::n_t Curr, }); } */ - return Identity::getInstance(); + return identityFlow(); } std::shared_ptr> @@ -160,7 +154,7 @@ IDEGeneralizedLCA::getCallFlowFunction(IDEGeneralizedLCA::n_t CallStmt, assert(llvm::isa(CallStmt)); if (isStringConstructor(DestMthd)) { // kill all data-flow facts at calls to string constructors - return killAllFlows(); + return killAllFlows(); } return std::make_shared( llvm::cast(CallStmt), DestMthd); @@ -196,7 +190,7 @@ IDEGeneralizedLCA::getCallToRetFlowFunction(IDEGeneralizedLCA::n_t CallSite, // found std::string ctor return generateFromZero(CS->getArgOperand(0)); } - // return lambdaFlow([Call](IDEGeneralizedLCA::d_t Source) + // return lambdaFlow([Call](IDEGeneralizedLCA::d_t Source) // -> std::set { // // llvm::outs() << "In getCallToRetFlowFunction\n"; // // llvm::outs() << llvmIRToString(Source) << '\n'; @@ -210,7 +204,7 @@ IDEGeneralizedLCA::getCallToRetFlowFunction(IDEGeneralizedLCA::n_t CallSite, // return {Source}; // }); } - return Identity::getInstance(); + return identityFlow(); } std::shared_ptr> @@ -249,7 +243,8 @@ IDEGeneralizedLCA::d_t IDEGeneralizedLCA::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IDEGeneralizedLCA::isZeroValue(IDEGeneralizedLCA::d_t Fact) const { +bool IDEGeneralizedLCA::isZeroValue( + IDEGeneralizedLCA::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index 98abfabbde..40de55d9bd 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -304,7 +304,7 @@ IDELinearConstantAnalysis::getNormalFlowFunction(n_t Curr, n_t /*Succ*/) { if (const auto *Load = llvm::dyn_cast(Curr)) { // only consider i32 load if (Load->getType()->isIntegerTy()) { - return generateFlowIf(Load, [Load](d_t Source) { + return generateFlowIf(Load, [Load](d_t Source) { return Source == Load->getPointerOperand(); }); } @@ -313,7 +313,7 @@ IDELinearConstantAnalysis::getNormalFlowFunction(n_t Curr, n_t /*Succ*/) { if (llvm::isa(Curr)) { auto *Lop = Curr->getOperand(0); auto *Rop = Curr->getOperand(1); - return generateFlowIf(Curr, [this, Lop, Rop](d_t Source) { + return generateFlowIf(Curr, [this, Lop, Rop](d_t Source) { /// Intentionally include nonlinear operations here for being able to /// explicitly set them to BOTTOM in the edge function return (Lop == Source) || (Rop == Source) || @@ -331,12 +331,12 @@ IDELinearConstantAnalysis::getNormalFlowFunction(n_t Curr, n_t /*Succ*/) { if (const auto *BinIntrinsic = llvm::dyn_cast(Agg)) { if (Extract->getType()->isIntegerTy()) { - return generateFlow(Curr, Agg); + return generateFlow(Curr, Agg); } } } - return identityFlow(); + return identityFlow(); } IDELinearConstantAnalysis::FlowFunctionPtrType @@ -351,7 +351,7 @@ IDELinearConstantAnalysis::getCallFlowFunction(n_t CallSite, f_t DestFun) { } } // Pass everything else as identity - return identityFlow(); + return identityFlow(); } IDELinearConstantAnalysis::FlowFunctionPtrType @@ -372,7 +372,7 @@ IDELinearConstantAnalysis::FlowFunctionPtrType IDELinearConstantAnalysis::getCallToRetFlowFunction( n_t CallSite, n_t /*RetSite*/, llvm::ArrayRef Callees) { if (llvm::all_of(Callees, [](f_t Fun) { return Fun->isDeclaration(); })) { - return identityFlow(); + return identityFlow(); } return mapFactsAlongsideCallSite( @@ -413,7 +413,7 @@ IDELinearConstantAnalysis::getSummaryFlowFunction(n_t Curr, f_t /*CalleeFun*/) { auto *Lop = BinIntrinsic->getLHS(); auto *Rop = BinIntrinsic->getRHS(); - return generateFlowIf(BinIntrinsic, [this, Lop, Rop](d_t Source) { + return generateFlowIf(BinIntrinsic, [this, Lop, Rop](d_t Source) { /// Intentionally include nonlinear operations here for being able to /// explicitly set them to BOTTOM in the edge function return (Lop == Source) || (Rop == Source) || @@ -430,7 +430,7 @@ IDELinearConstantAnalysis::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IDELinearConstantAnalysis::isZeroValue(d_t Fact) const { +bool IDELinearConstantAnalysis::isZeroValue(d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp index e40ec7a5fc..fcc2242f86 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp @@ -38,26 +38,26 @@ IDEProtoAnalysis::IDEProtoAnalysis(const LLVMProjectIRDB *IRDB, IDEProtoAnalysis::FlowFunctionPtrType IDEProtoAnalysis::getNormalFlowFunction(IDEProtoAnalysis::n_t /*Curr*/, IDEProtoAnalysis::n_t /*Succ*/) { - return Identity::getInstance(); + return identityFlow(); } IDEProtoAnalysis::FlowFunctionPtrType IDEProtoAnalysis::getCallFlowFunction(IDEProtoAnalysis::n_t /*CallSite*/, IDEProtoAnalysis::f_t /*DestFun*/) { - return Identity::getInstance(); + return identityFlow(); } IDEProtoAnalysis::FlowFunctionPtrType IDEProtoAnalysis::getRetFlowFunction( IDEProtoAnalysis::n_t /*CallSite*/, IDEProtoAnalysis::f_t /*CalleeFun*/, IDEProtoAnalysis::n_t /*ExitSite*/, IDEProtoAnalysis::n_t /*RetSite*/) { - return Identity::getInstance(); + return identityFlow(); } IDEProtoAnalysis::FlowFunctionPtrType IDEProtoAnalysis::getCallToRetFlowFunction(IDEProtoAnalysis::n_t /*CallSite*/, IDEProtoAnalysis::n_t /*RetSite*/, llvm::ArrayRef /*Callees*/) { - return Identity::getInstance(); + return identityFlow(); } IDEProtoAnalysis::FlowFunctionPtrType @@ -79,7 +79,7 @@ IDEProtoAnalysis::d_t IDEProtoAnalysis::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IDEProtoAnalysis::isZeroValue(IDEProtoAnalysis::d_t Fact) const { +bool IDEProtoAnalysis::isZeroValue(IDEProtoAnalysis::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp index 6e7d869da9..2ba44060d2 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp @@ -62,13 +62,13 @@ IDESecureHeapPropagation::IDESecureHeapPropagation( IDESecureHeapPropagation::FlowFunctionPtrType IDESecureHeapPropagation::getNormalFlowFunction(n_t /*Curr*/, n_t /*Succ*/) { - return Identity::getInstance(); + return identityFlow(); } IDESecureHeapPropagation::FlowFunctionPtrType IDESecureHeapPropagation::getCallFlowFunction(n_t /*CallSite*/, f_t /*DestMthd*/) { - return Identity::getInstance(); + return identityFlow(); } IDESecureHeapPropagation::FlowFunctionPtrType @@ -76,7 +76,7 @@ IDESecureHeapPropagation::getRetFlowFunction(n_t /*CallSite*/, f_t /*CalleeMthd*/, n_t /*ExitInst*/, n_t /*RetSite*/) { - return Identity::getInstance(); + return identityFlow(); } IDESecureHeapPropagation::FlowFunctionPtrType @@ -90,7 +90,7 @@ IDESecureHeapPropagation::getCallToRetFlowFunction( if (FName == InitializerFn) { return generateFromZero(SecureHeapFact::INITIALIZED); } - return Identity::getInstance(); + return identityFlow(); } IDESecureHeapPropagation::FlowFunctionPtrType IDESecureHeapPropagation::getSummaryFlowFunction(n_t /*CallSite*/, @@ -109,7 +109,7 @@ IDESecureHeapPropagation::createZeroValue() const { return SecureHeapFact::ZERO; } -bool IDESecureHeapPropagation::isZeroValue(d_t Fact) const { +bool IDESecureHeapPropagation::isZeroValue(d_t Fact) const noexcept { return Fact == SecureHeapFact::ZERO; } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp index ba1d9b8482..bb759d32ef 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp @@ -42,26 +42,26 @@ IDESolverTest::IDESolverTest(const LLVMProjectIRDB *IRDB, IDESolverTest::FlowFunctionPtrType IDESolverTest::getNormalFlowFunction(IDESolverTest::n_t /*Curr*/, IDESolverTest::n_t /*Succ*/) { - return Identity::getInstance(); + return identityFlow(); } IDESolverTest::FlowFunctionPtrType IDESolverTest::getCallFlowFunction(IDESolverTest::n_t /*CallSite*/, IDESolverTest::f_t /*DestFun*/) { - return Identity::getInstance(); + return identityFlow(); } IDESolverTest::FlowFunctionPtrType IDESolverTest::getRetFlowFunction( IDESolverTest::n_t /*CallSite*/, IDESolverTest::f_t /*CalleeFun*/, IDESolverTest::n_t /*ExitStmt*/, IDESolverTest::n_t /*RetSite*/) { - return Identity::getInstance(); + return identityFlow(); } IDESolverTest::FlowFunctionPtrType IDESolverTest::getCallToRetFlowFunction(IDESolverTest::n_t /*CallSite*/, IDESolverTest::n_t /*RetSite*/, llvm::ArrayRef /*Callees*/) { - return Identity::getInstance(); + return identityFlow(); } IDESolverTest::FlowFunctionPtrType @@ -82,7 +82,7 @@ IDESolverTest::d_t IDESolverTest::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IDESolverTest::isZeroValue(IDESolverTest::d_t Fact) const { +bool IDESolverTest::isZeroValue(IDESolverTest::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp index 5033fff0b3..cb5c01d627 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp @@ -211,7 +211,7 @@ IDETypeStateAnalysis::getNormalFlowFunction( } if (const auto *Gep = llvm::dyn_cast(Curr)) { if (hasMatchingType(Gep->getPointerOperand())) { - return lambdaFlow([=](d_t Source) -> std::set { + return lambdaFlow([=](d_t Source) -> std::set { // if (Source == Gep->getPointerOperand()) { // return {Source, Gep}; //} @@ -257,7 +257,7 @@ IDETypeStateAnalysis::getNormalFlowFunction( return std::make_shared(Store, RelevantAliasesAndAllocas); } } - return Identity::getInstance(); + return identityFlow(); } IDETypeStateAnalysis::FlowFunctionPtrType @@ -266,7 +266,7 @@ IDETypeStateAnalysis::getCallFlowFunction(IDETypeStateAnalysis::n_t CallSite, // Kill all data-flow facts if we hit a function of the target API. // Those functions are modled within Call-To-Return. if (TSD->isAPIFunction(llvm::demangle(DestFun->getName().str()))) { - return killAllFlows(); + return killAllFlows(); } // Otherwise, if we have an ordinary function call, we can just use the // standard mapping. @@ -411,12 +411,12 @@ IDETypeStateAnalysis::getCallToRetFlowFunction( if (!TSD->isAPIFunction(DemangledFname) && !Callee->isDeclaration()) { for (const auto &Arg : CS->args()) { if (hasMatchingType(Arg)) { - return killManyFlows(getWMAliasesAndAllocas(Arg.get())); + return killManyFlows(getWMAliasesAndAllocas(Arg.get())); } } } } - return Identity::getInstance(); + return identityFlow(); } IDETypeStateAnalysis::FlowFunctionPtrType @@ -438,7 +438,8 @@ IDETypeStateAnalysis::d_t IDETypeStateAnalysis::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IDETypeStateAnalysis::isZeroValue(IDETypeStateAnalysis::d_t Fact) const { +bool IDETypeStateAnalysis::isZeroValue( + IDETypeStateAnalysis::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp index 0213a77ad2..e8cd058a30 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp @@ -53,7 +53,7 @@ IFDSConstAnalysis::getNormalFlowFunction(IFDSConstAnalysis::n_t Curr, // If the store instruction sets up or updates the vtable, i.e. value // operand is vtable pointer, ignore it! if (isTouchVTableInst(Store)) { - return Identity::getInstance(); + return identityFlow(); } IFDSConstAnalysis::d_t PointerOp = Store->getPointerOperand(); @@ -87,7 +87,7 @@ IFDSConstAnalysis::getNormalFlowFunction(IFDSConstAnalysis::n_t Curr, } /* end store instruction */ // Pass everything else as identity - return Identity::getInstance(); + return identityFlow(); } IFDSConstAnalysis::FlowFunctionPtrType @@ -97,7 +97,7 @@ IFDSConstAnalysis::getCallFlowFunction(IFDSConstAnalysis::n_t CallSite, // memset) if (llvm::isa(CallSite)) { PHASAR_LOG_LEVEL(DEBUG, "Call statement is a LLVM MemIntrinsic!"); - return killAllFlows(); + return killAllFlows(); } // Check if its a Call Instruction or an Invoke Instruction. If so, we // need to map all actual parameters into formal parameters. @@ -111,7 +111,7 @@ IFDSConstAnalysis::getCallFlowFunction(IFDSConstAnalysis::n_t CallSite, } /* end call/invoke instruction */ // Pass everything else as identity - return Identity::getInstance(); + return identityFlow(); } IFDSConstAnalysis::FlowFunctionPtrType IFDSConstAnalysis::getRetFlowFunction( @@ -152,7 +152,7 @@ IFDSConstAnalysis::getCallToRetFlowFunction(IFDSConstAnalysis::n_t CallSite, } // Pass everything else as identity - return Identity::getInstance(); + return identityFlow(); } IFDSConstAnalysis::FlowFunctionPtrType @@ -174,7 +174,8 @@ IFDSConstAnalysis::d_t IFDSConstAnalysis::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IFDSConstAnalysis::isZeroValue(IFDSConstAnalysis::d_t Fact) const { +bool IFDSConstAnalysis::isZeroValue( + IFDSConstAnalysis::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp index 1e3f7b4590..39e250f791 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp @@ -34,32 +34,32 @@ IFDSProtoAnalysis::getNormalFlowFunction(IFDSProtoAnalysis::n_t Curr, if (const auto *Store = llvm::dyn_cast(Curr)) { return generateFromZero(Store->getPointerOperand()); } - return Identity::getInstance(); + return identityFlow(); } IFDSProtoAnalysis::FlowFunctionPtrType IFDSProtoAnalysis::getCallFlowFunction(IFDSProtoAnalysis::n_t /*CallSite*/, IFDSProtoAnalysis::f_t /*DestFun*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSProtoAnalysis::FlowFunctionPtrType IFDSProtoAnalysis::getRetFlowFunction( IFDSProtoAnalysis::n_t /*CallSite*/, IFDSProtoAnalysis::f_t /*CalleeFun*/, IFDSProtoAnalysis::n_t /*ExitInst*/, IFDSProtoAnalysis::n_t /*RetSite*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSProtoAnalysis::FlowFunctionPtrType IFDSProtoAnalysis::getCallToRetFlowFunction(IFDSProtoAnalysis::n_t /*CallSite*/, IFDSProtoAnalysis::n_t /*RetSite*/, llvm::ArrayRef /*Callees*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSProtoAnalysis::FlowFunctionPtrType IFDSProtoAnalysis::getSummaryFlowFunction(IFDSProtoAnalysis::n_t /*CallSite*/, IFDSProtoAnalysis::f_t /*DestFun*/) { - return Identity::getInstance(); + return identityFlow(); } InitialSeeds::getInstance(); + return identityFlow(); } IFDSSignAnalysis::FlowFunctionPtrType IFDSSignAnalysis::getCallFlowFunction(IFDSSignAnalysis::n_t /*CallSite*/, IFDSSignAnalysis::f_t /*DestFun*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSSignAnalysis::FlowFunctionPtrType IFDSSignAnalysis::getRetFlowFunction( IFDSSignAnalysis::n_t /*CallSite*/, IFDSSignAnalysis::f_t /*CalleeFun*/, IFDSSignAnalysis::n_t /*ExitStmt*/, IFDSSignAnalysis::n_t /*RetSite*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSSignAnalysis::FlowFunctionPtrType IFDSSignAnalysis::getCallToRetFlowFunction(IFDSSignAnalysis::n_t /*CallSite*/, IFDSSignAnalysis::n_t /*RetSite*/, llvm::ArrayRef /*Callees*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSSignAnalysis::FlowFunctionPtrType IFDSSignAnalysis::getSummaryFlowFunction(IFDSSignAnalysis::n_t /*CallSite*/, IFDSSignAnalysis::f_t /*DestFun*/) { - return Identity::getInstance(); + return identityFlow(); } InitialSeeds::getInstance(); + return identityFlow(); } IFDSSolverTest::FlowFunctionPtrType IFDSSolverTest::getCallFlowFunction(IFDSSolverTest::n_t /*CallSite*/, IFDSSolverTest::f_t /*DestFun*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSSolverTest::FlowFunctionPtrType IFDSSolverTest::getRetFlowFunction( IFDSSolverTest::n_t /*CallSite*/, IFDSSolverTest::f_t /*CalleeFun*/, IFDSSolverTest::n_t /*ExitStmt*/, IFDSSolverTest::n_t /*RetSite*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSSolverTest::FlowFunctionPtrType IFDSSolverTest::getCallToRetFlowFunction(IFDSSolverTest::n_t /*CallSite*/, IFDSSolverTest::n_t /*RetSite*/, llvm::ArrayRef /*Callees*/) { - return Identity::getInstance(); + return identityFlow(); } IFDSSolverTest::FlowFunctionPtrType @@ -69,7 +69,7 @@ IFDSSolverTest::d_t IFDSSolverTest::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IFDSSolverTest::isZeroValue(IFDSSolverTest::d_t Fact) const { +bool IFDSSolverTest::isZeroValue(IFDSSolverTest::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index ddf60d0160..f49d22c5a6 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -158,7 +158,7 @@ auto IFDSTaintAnalysis::getNormalFlowFunction(n_t Curr, populateWithMayAliases(Gen, Store); Gen.insert(Store->getValueOperand()); - return lambdaFlow( + return lambdaFlow( [Store, Gen{std::move(Gen)}](d_t Source) -> container_type { if (Store->getValueOperand() == Source) { return Gen; @@ -185,7 +185,7 @@ auto IFDSTaintAnalysis::getNormalFlowFunction(n_t Curr, } if (const auto *Insert = llvm::dyn_cast(Curr)) { - return lambdaFlow([Insert](d_t Source) -> container_type { + return lambdaFlow([Insert](d_t Source) -> container_type { if (Source == Insert->getAggregateOperand() || Source == Insert->getInsertedValueOperand()) { return {Source, Insert}; @@ -200,11 +200,11 @@ auto IFDSTaintAnalysis::getNormalFlowFunction(n_t Curr, } if (const auto *Cast = llvm::dyn_cast(Curr)) { - return transferFlow(Cast, Cast->getOperand(0)); + return transferFlow(Cast, Cast->getOperand(0)); } // Otherwise we do not care and leave everything as it is - return Identity::getInstance(); + return identityFlow(); } auto IFDSTaintAnalysis::getCallFlowFunction(n_t CallSite, f_t DestFun) @@ -215,7 +215,7 @@ auto IFDSTaintAnalysis::getCallFlowFunction(n_t CallSite, f_t DestFun) // The respective taints or leaks are then generated in the corresponding // call to return flow function. if (isSourceCall(CS, DestFun) || isSinkCall(CS, DestFun)) { - return killAllFlows(); + return killAllFlows(); } // Map the actual into the formal parameters @@ -262,7 +262,7 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, if (DestFun->getName().equals("$sSS1poiyS2S_SStFZ")) { const auto *CS = llvm::cast(CallSite); - return generateFlowIf(CallSite, [CS](d_t Source) { + return generateFlowIf(CallSite, [CS](d_t Source) { return ((Source == CS->getArgOperand(1)) || (Source == CS->getArgOperand(3))); }); @@ -295,8 +295,8 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, if (Gen.empty()) { if (!Leak.empty() || !Kill.empty()) { - return lambdaFlow([Leak{std::move(Leak)}, Kill{std::move(Kill)}, - this, CallSite](d_t Source) -> container_type { + 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); } @@ -316,8 +316,8 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite, // Gen nonempty Gen.insert(LLVMZeroValue::getInstance()); - return lambdaFlow([Gen{std::move(Gen)}, Leak{std::move(Leak)}, this, - CallSite](d_t Source) -> container_type { + return lambdaFlow([Gen{std::move(Gen)}, Leak{std::move(Leak)}, this, + CallSite](d_t Source) -> container_type { if (LLVMZeroValue::isLLVMZeroValue(Source)) { return Gen; } @@ -355,7 +355,7 @@ auto IFDSTaintAnalysis::createZeroValue() const -> d_t { return LLVMZeroValue::getInstance(); } -bool IFDSTaintAnalysis::isZeroValue(d_t FlowFact) const { +bool IFDSTaintAnalysis::isZeroValue(d_t FlowFact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(FlowFact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp index 53ff5c972b..37eb656605 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp @@ -94,7 +94,7 @@ IFDSTypeAnalysis::d_t IFDSTypeAnalysis::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IFDSTypeAnalysis::isZeroValue(IFDSTypeAnalysis::d_t Fact) const { +bool IFDSTypeAnalysis::isZeroValue(IFDSTypeAnalysis::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp index 2537972d96..a527b4332f 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp @@ -167,26 +167,24 @@ IFDSUninitializedVariables::getNormalFlowFunction( } if (const auto *Alloc = llvm::dyn_cast(Curr)) { - return lambdaFlow( - [Alloc, this](IFDSUninitializedVariables::d_t Source) - -> std::set { - if (isZeroValue(Source)) { - if (Alloc->getAllocatedType()->isIntegerTy() || - Alloc->getAllocatedType()->isFloatingPointTy() || - Alloc->getAllocatedType()->isPointerTy() || - Alloc->getAllocatedType()->isArrayTy()) { - //------------------------------------------------------------ - // Why not generate for structs, but for arrays? (would be - // consistent to generate either both or none of them) - //------------------------------------------------------------ - - // generate the alloca - return {Source, Alloc}; - } - } - // otherwise propagate all facts - return {Source}; - }); + return lambdaFlow([Alloc, this](d_t Source) -> std::set { + if (isZeroValue(Source)) { + if (Alloc->getAllocatedType()->isIntegerTy() || + Alloc->getAllocatedType()->isFloatingPointTy() || + Alloc->getAllocatedType()->isPointerTy() || + Alloc->getAllocatedType()->isArrayTy()) { + //------------------------------------------------------------ + // Why not generate for structs, but for arrays? (would be + // consistent to generate either both or none of them) + //------------------------------------------------------------ + + // generate the alloca + return {Source, Alloc}; + } + } + // otherwise propagate all facts + return {Source}; + }); } // check if some instruction is using an undefined value (in)directly struct UVFF : FlowFunction { @@ -303,7 +301,7 @@ IFDSUninitializedVariables::getCallFlowFunction( }; return std::make_shared(DestFun, CS, getZeroValue()); } - return Identity::getInstance(); + return identityFlow(); } IFDSUninitializedVariables::FlowFunctionPtrType @@ -348,7 +346,7 @@ IFDSUninitializedVariables::getRetFlowFunction( return std::make_shared(CS, ExitStmt); } // kill everything else - return killAllFlows(); + return killAllFlows(); } IFDSUninitializedVariables::FlowFunctionPtrType @@ -360,23 +358,21 @@ IFDSUninitializedVariables::getCallToRetFlowFunction( // Handle pointer/reference parameters //---------------------------------------------------------------------- if (const auto *CS = llvm::dyn_cast(CallSite)) { - return lambdaFlow( - [CS](IFDSUninitializedVariables::d_t Source) - -> std::set { - if (Source->getType()->isPointerTy()) { - for (const auto &Arg : CS->args()) { - if (Arg.get() == Source) { - // do not propagate pointer arguments, since the function may - // initialize them (would be much more precise with - // field-sensitivity) - return {}; - } - } + return lambdaFlow([CS](d_t Source) -> std::set { + if (Source->getType()->isPointerTy()) { + for (const auto &Arg : CS->args()) { + if (Arg.get() == Source) { + // do not propagate pointer arguments, since the function may + // initialize them (would be much more precise with + // field-sensitivity) + return {}; } - return {Source}; - }); + } + } + return {Source}; + }); } - return Identity::getInstance(); + return identityFlow(); } IFDSUninitializedVariables::FlowFunctionPtrType @@ -401,7 +397,7 @@ IFDSUninitializedVariables::createZeroValue() const { } bool IFDSUninitializedVariables::isZeroValue( - IFDSUninitializedVariables::d_t Fact) const { + IFDSUninitializedVariables::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } From dfb2c43bdf3257344a51ec377f141da68f8f96ca Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Tue, 15 Aug 2023 19:46:11 +0200 Subject: [PATCH 3/4] pre-commit TypeTraits.h --- include/phasar/Utils/TypeTraits.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/phasar/Utils/TypeTraits.h b/include/phasar/Utils/TypeTraits.h index a1af1ec4f6..a069bcb5c4 100644 --- a/include/phasar/Utils/TypeTraits.h +++ b/include/phasar/Utils/TypeTraits.h @@ -255,7 +255,6 @@ template struct DefaultConstruct { } }; - template void reserveIfPossible(T &Container, size_t Capacity) { if constexpr (detail::has_reserve::value) { Container.reserve(Capacity); From d4735c6f359e256f73ccdf2dcd54b0c259a6166b Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 24 Aug 2023 20:15:10 +0200 Subject: [PATCH 4/4] Merge branch 'development' into f-DefaultAllTopFn --- .clang-tidy | 2 +- .../DataFlow/IfdsIde/IDETabulationProblem.h | 4 - .../DataFlow/IfdsIde/IFDSTabulationProblem.h | 4 - .../phasar/DataFlow/IfdsIde/InitialSeeds.h | 2 +- .../IfdsIde/Solver/FlowEdgeFunctionCache.h | 103 +-- .../DataFlow/IfdsIde/Solver/IDESolver.h | 216 +++--- .../DataFlow/IfdsIde/Solver/JumpFunctions.h | 47 +- .../phasar/DataFlow/IfdsIde/SolverResults.h | 16 +- .../DataFlow/Mono/Contexts/CallStringCTX.h | 5 +- .../phasar/DataFlow/Mono/IntraMonoProblem.h | 7 +- .../DataFlow/Mono/Solver/InterMonoSolver.h | 31 +- .../DataFlow/Mono/Solver/IntraMonoSolver.h | 6 +- .../Problems/IDEExtendedTaintAnalysis.h | 8 - .../IDEGeneralizedLCA/IDEGeneralizedLCA.h | 9 - .../Problems/IDEInstInteractionAnalysis.h | 23 +- .../Problems/IDELinearConstantAnalysis.h | 8 - .../IfdsIde/Problems/IDEProtoAnalysis.h | 8 - .../Problems/IDESecureHeapPropagation.h | 12 +- .../DataFlow/IfdsIde/Problems/IDESolverTest.h | 8 - .../IfdsIde/Problems/IDETypeStateAnalysis.h | 617 ++++++++++++--- .../IfdsIde/Problems/IFDSConstAnalysis.h | 6 - .../Problems/IFDSFieldSensTaintAnalysis.h | 31 +- .../IfdsIde/Problems/IFDSProtoAnalysis.h | 6 - .../IfdsIde/Problems/IFDSSignAnalysis.h | 6 - .../IfdsIde/Problems/IFDSSolverTest.h | 6 - .../IfdsIde/Problems/IFDSTaintAnalysis.h | 6 - .../IfdsIde/Problems/IFDSTypeAnalysis.h | 6 - .../Problems/IFDSUninitializedVariables.h | 6 - .../CSTDFILEIOTypeStateDescription.h | 80 +- .../OpenSSLEVPKDFCTXDescription.h | 88 +-- .../OpenSSLEVPKDFDescription.h | 60 +- .../OpenSSLSecureHeapDescription.h | 46 +- .../OpenSSLSecureMemoryDescription.h | 43 +- .../TypeStateDescription.h | 36 +- .../InterMonoFullConstantPropagation.h | 6 - .../Mono/Problems/InterMonoSolverTest.h | 6 - .../Mono/Problems/InterMonoTaintAnalysis.h | 6 - .../IntraMonoFullConstantPropagation.h | 28 +- .../Mono/Problems/IntraMonoSolverTest.h | 7 - .../Mono/Problems/IntraMonoUninitVariables.h | 6 - include/phasar/Utils/Printer.h | 173 +++-- include/phasar/Utils/TypeTraits.h | 2 + .../AnalysisControllerXIDECSTDIOTS.cpp | 3 +- .../AnalysisControllerXIDEOpenSSLTS.cpp | 3 +- .../Problems/IDEExtendedTaintAnalysis.cpp | 27 +- .../IDEGeneralizedLCA/IDEGeneralizedLCA.cpp | 54 +- .../Problems/IDELinearConstantAnalysis.cpp | 34 +- .../IfdsIde/Problems/IDEProtoAnalysis.cpp | 20 - .../Problems/IDESecureHeapPropagation.cpp | 72 +- .../IfdsIde/Problems/IDESolverTest.cpp | 20 - .../IfdsIde/Problems/IDETypeStateAnalysis.cpp | 724 ++++-------------- .../IfdsIde/Problems/IFDSConstAnalysis.cpp | 15 - .../Problems/IFDSFieldSensTaintAnalysis.cpp | 24 + .../IfdsIde/Problems/IFDSProtoAnalysis.cpp | 15 - .../IfdsIde/Problems/IFDSSignAnalysis.cpp | 15 - .../IfdsIde/Problems/IFDSSolverTest.cpp | 15 - .../IfdsIde/Problems/IFDSTaintAnalysis.cpp | 13 - .../IfdsIde/Problems/IFDSTypeAnalysis.cpp | 15 - .../Problems/IFDSUninitializedVariables.cpp | 22 +- .../CSTDFILEIOTypeStateDescription.cpp | 157 ++-- .../OpenSSLEVPKDFCTXDescription.cpp | 137 ++-- .../OpenSSLEVPKDFDescription.cpp | 67 +- .../OpenSSLSecureHeapDescription.cpp | 100 ++- .../OpenSSLSecureMemoryDescription.cpp | 163 ++-- .../InterMonoFullConstantPropagation.cpp | 15 - .../Mono/Problems/InterMonoSolverTest.cpp | 15 - .../Mono/Problems/InterMonoTaintAnalysis.cpp | 14 - .../IntraMonoFullConstantPropagation.cpp | 32 +- .../Mono/Problems/IntraMonoSolverTest.cpp | 15 - .../Problems/IntraMonoUninitVariables.cpp | 15 - lib/PhasarLLVM/Utils/LLVMPrinter.cpp | 14 + tools/example-tool/myphasartool.cpp | 4 +- .../Problems/IDETSAnalysisFileIOTest.cpp | 10 +- .../IDETSAnalysisOpenSSLEVPKDFTest.cpp | 403 +++++----- .../IDETSAnalysisOpenSSLSecureHeapTest.cpp | 24 +- .../IDETSAnalysisOpenSSLSecureMemoryTest.cpp | 23 +- 76 files changed, 1788 insertions(+), 2307 deletions(-) create mode 100644 lib/PhasarLLVM/Utils/LLVMPrinter.cpp diff --git a/.clang-tidy b/.clang-tidy index 93ad42fe90..063d1090aa 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -55,7 +55,7 @@ CheckOptions: - key: readability-identifier-naming.ParameterIgnoredRegexp value: (d|d1|d2|d3|d4|d5|eP|f|n) - key: readability-identifier-naming.FunctionIgnoredRegexp - value: (try_emplace|from_json|to_json|equal_to|to_string) + value: (try_emplace|from_json|to_json|equal_to|to_string|DToString|NToString|FToString|LToString) - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index 0f373bc14b..ab20dc3f6e 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -57,12 +57,8 @@ class AllTopFnProvider< template > class IDETabulationProblem : public FlowFunctions, - public NodePrinter, - public DataFlowFactPrinter, - public FunctionPrinter, public EdgeFunctions, public JoinLattice, - public EdgeFactPrinter, public AllTopFnProvider { public: using ProblemAnalysisDomain = AnalysisDomainTy; diff --git a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h index 59914521be..e669a26a9d 100644 --- a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h @@ -76,10 +76,6 @@ class IFDSTabulationProblem d_t /*SuccNode*/) final { return EdgeIdentity{}; } - - void printEdgeFact(llvm::raw_ostream &OS, BinaryDomain Val) const final { - OS << Val; - } }; } // namespace psr diff --git a/include/phasar/DataFlow/IfdsIde/InitialSeeds.h b/include/phasar/DataFlow/IfdsIde/InitialSeeds.h index b5a001031e..60e5ae23e3 100644 --- a/include/phasar/DataFlow/IfdsIde/InitialSeeds.h +++ b/include/phasar/DataFlow/IfdsIde/InitialSeeds.h @@ -46,7 +46,7 @@ template class InitialSeeds { } void addSeed(N Node, D Fact, L Value) { - Seeds[Node][Fact] = std::move(Value); + Seeds[std::move(Node)].insert_or_assign(std::move(Fact), std::move(Value)); } [[nodiscard]] size_t countInitialSeeds() const { diff --git a/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h b/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h index a670a403fd..484606935c 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h @@ -188,8 +188,8 @@ class FlowEdgeFunctionCache { PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Normal flow function factory call"); - PHASAR_LOG_LEVEL(DEBUG, "(N) Curr Inst : " << Problem.NtoString(Curr)); - PHASAR_LOG_LEVEL(DEBUG, "(N) Succ Inst : " << Problem.NtoString(Succ))); + PHASAR_LOG_LEVEL(DEBUG, "(N) Curr Inst : " << NToString(Curr)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Succ Inst : " << NToString(Succ))); auto Key = createEdgeFunctionInstKey(Curr, Succ); auto SearchNormalFlowFunction = NormalFunctionCache.find(Key); if (SearchNormalFlowFunction != NormalFunctionCache.end()) { @@ -218,11 +218,10 @@ class FlowEdgeFunctionCache { FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) { PAMM_GET_INSTANCE; - IF_LOG_ENABLED(PHASAR_LOG_LEVEL(DEBUG, "Call flow function factory call"); - PHASAR_LOG_LEVEL(DEBUG, "(N) Call Stmt : " - << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL( - DEBUG, "(F) Dest Fun : " << Problem.FtoString(DestFun))); + IF_LOG_ENABLED( + PHASAR_LOG_LEVEL(DEBUG, "Call flow function factory call"); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Stmt : " << NToString(CallSite)); + PHASAR_LOG_LEVEL(DEBUG, "(F) Dest Fun : " << FToString(DestFun))); auto Key = std::tie(CallSite, DestFun); auto SearchCallFlowFunction = CallFlowFunctionCache.find(Key); if (SearchCallFlowFunction != CallFlowFunctionCache.end()) { @@ -245,14 +244,10 @@ class FlowEdgeFunctionCache { PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Return flow function factory call"); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Call Site : " << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(F) Callee : " << Problem.FtoString(CalleeFun)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Exit Stmt : " << Problem.NtoString(ExitInst)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Ret Site : " << Problem.NtoString(RetSite))); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Site : " << NToString(CallSite)); + PHASAR_LOG_LEVEL(DEBUG, "(F) Callee : " << FToString(CalleeFun)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Exit Stmt : " << NToString(ExitInst)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Ret Site : " << NToString(RetSite))); auto Key = std::tie(CallSite, CalleeFun, ExitInst, RetSite); auto SearchReturnFlowFunction = ReturnFlowFunctionCache.find(Key); if (SearchReturnFlowFunction != ReturnFlowFunctionCache.end()) { @@ -279,13 +274,11 @@ class FlowEdgeFunctionCache { IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Call-to-Return flow function factory call"); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Call Site : " << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Ret Site : " << Problem.NtoString(RetSite)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Site : " << NToString(CallSite)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Ret Site : " << NToString(RetSite)); PHASAR_LOG_LEVEL(DEBUG, "(F) Callee's : "); for (auto callee : Callees) { - PHASAR_LOG_LEVEL(DEBUG, " " << Problem.FtoString(callee)); + PHASAR_LOG_LEVEL(DEBUG, " " << FToString(callee)); };); auto Key = std::tie(CallSite, RetSite); auto SearchCallToRetFlowFunction = CallToRetFlowFunctionCache.find(Key); @@ -311,10 +304,8 @@ class FlowEdgeFunctionCache { // INC_COUNTER("Summary-FF Construction", 1, Full); IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Summary flow function factory call"); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Call Stmt : " << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(F) Dest Mthd : " << Problem.FtoString(DestFun)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Stmt : " << NToString(CallSite)); + PHASAR_LOG_LEVEL(DEBUG, "(F) Dest Mthd : " << FToString(DestFun)); PHASAR_LOG_LEVEL(DEBUG, ' ')); auto FF = Problem.getSummaryFlowFunction(CallSite, DestFun); return FF; @@ -325,12 +316,10 @@ class FlowEdgeFunctionCache { PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Normal edge function factory call"); - PHASAR_LOG_LEVEL(DEBUG, "(N) Curr Inst : " << Problem.NtoString(Curr)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Curr Node : " << Problem.DtoString(CurrNode)); - PHASAR_LOG_LEVEL(DEBUG, "(N) Succ Inst : " << Problem.NtoString(Succ)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Succ Node : " << Problem.DtoString(SuccNode))); + PHASAR_LOG_LEVEL(DEBUG, "(N) Curr Inst : " << NToString(Curr)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Curr Node : " << DToString(CurrNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Succ Inst : " << NToString(Succ)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Succ Node : " << DToString(SuccNode))); EdgeFuncInstKey OuterMapKey = createEdgeFunctionInstKey(Curr, Succ); auto SearchInnerMap = NormalFunctionCache.find(OuterMapKey); @@ -371,15 +360,12 @@ class FlowEdgeFunctionCache { PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Call edge function factory call"); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Call Stmt : " << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Src Node : " << Problem.DtoString(SrcNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Stmt : " << NToString(CallSite)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Src Node : " << DToString(SrcNode)); - PHASAR_LOG_LEVEL( - DEBUG, "(F) Dest Fun : " << Problem.FtoString(DestinationFunction)); PHASAR_LOG_LEVEL(DEBUG, - "(D) Dest Node : " << Problem.DtoString(DestNode))); + "(F) Dest Fun : " << FToString(DestinationFunction)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Dest Node : " << DToString(DestNode))); auto Key = std::tie(CallSite, SrcNode, DestinationFunction, DestNode); auto SearchCallEdgeFunction = CallEdgeFunctionCache.find(Key); if (SearchCallEdgeFunction != CallEdgeFunctionCache.end()) { @@ -404,18 +390,13 @@ class FlowEdgeFunctionCache { PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Return edge function factory call"); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Site : " << NToString(CallSite)); PHASAR_LOG_LEVEL(DEBUG, - "(N) Call Site : " << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL( - DEBUG, "(F) Callee : " << Problem.FtoString(CalleeFunction)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Exit Stmt : " << Problem.NtoString(ExitInst)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Exit Node : " << Problem.DtoString(ExitNode)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Ret Site : " << Problem.NtoString(RetSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Ret Node : " << Problem.DtoString(RetNode))); + "(F) Callee : " << FToString(CalleeFunction)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Exit Stmt : " << NToString(ExitInst)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Exit Node : " << DToString(ExitNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Ret Site : " << NToString(RetSite)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Ret Node : " << DToString(RetNode))); auto Key = std::tie(CallSite, CalleeFunction, ExitInst, ExitNode, RetSite, RetNode); auto SearchReturnEdgeFunction = ReturnEdgeFunctionCache.find(Key); @@ -442,18 +423,14 @@ class FlowEdgeFunctionCache { IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Call-to-Return edge function factory call"); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Call Site : " << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Call Node : " << Problem.DtoString(CallNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Site : " << NToString(CallSite)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Call Node : " << DToString(CallNode)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Ret Site : " << Problem.NtoString(RetSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Ret Node : " << Problem.DtoString(RetSiteNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Ret Site : " << NToString(RetSite)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Ret Node : " << DToString(RetSiteNode)); PHASAR_LOG_LEVEL(DEBUG, "(F) Callee's : "); for (auto callee : Callees) { - PHASAR_LOG_LEVEL(DEBUG, " " << Problem.FtoString(callee)); + PHASAR_LOG_LEVEL(DEBUG, " " << FToString(callee)); }); EdgeFuncInstKey OuterMapKey = createEdgeFunctionInstKey(CallSite, RetSite); @@ -498,14 +475,10 @@ class FlowEdgeFunctionCache { PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Summary edge function factory call"); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Call Site : " << Problem.NtoString(CallSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Call Node : " << Problem.DtoString(CallNode)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Ret Site : " << Problem.NtoString(RetSite)); - PHASAR_LOG_LEVEL(DEBUG, - "(D) Ret Node : " << Problem.DtoString(RetSiteNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Call Site : " << NToString(CallSite)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Call Node : " << DToString(CallNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Ret Site : " << NToString(RetSite)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Ret Node : " << DToString(RetSiteNode)); PHASAR_LOG_LEVEL(DEBUG, ' ')); auto Key = std::tie(CallSite, CallNode, RetSite, RetSiteNode); auto SearchSummaryEdgeFunction = SummaryEdgeFunctionCache.find(Key); diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h index 41207a44d3..669bd108d7 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h @@ -82,8 +82,7 @@ class IDESolver : IDEProblem(Problem), ZeroValue(Problem.getZeroValue()), ICF(ICF), SolverConfig(Problem.getIFDSIDESolverConfig()), CachedFlowEdgeFunctions(Problem), AllTop(Problem.allTopFunction()), - JumpFn(std::make_shared>( - IDEProblem)), + JumpFn(std::make_shared>()), Seeds(Problem.initialSeeds()) { assert(ICF != nullptr); } @@ -110,21 +109,16 @@ class IDESolver n_t Curr; for (unsigned I = 0; I < Cells.size(); ++I) { Curr = Cells[I].getRowKey(); - auto NStr = llvm::StringRef(IDEProblem.NtoString(Cells[I].getRowKey())) - .trim() - .str(); + auto NStr = + llvm::StringRef(NToString(Cells[I].getRowKey())).trim().str(); std::string NodeStr = ICF->getFunctionName(ICF->getFunctionOf(Curr)) + "::" + NStr; J[DataFlowID][NodeStr]; std::string FactStr = - llvm::StringRef(IDEProblem.DtoString(Cells[I].getColumnKey())) - .trim() - .str(); + llvm::StringRef(DToString(Cells[I].getColumnKey())).trim().str(); std::string ValueStr = - llvm::StringRef(IDEProblem.LtoString(Cells[I].getValue())) - .trim() - .str(); + llvm::StringRef(LToString(Cells[I].getValue())).trim().str(); J[DataFlowID][NodeStr]["Facts"] += {FactStr, ValueStr}; } } @@ -198,7 +192,7 @@ class IDESolver } void dumpResults(llvm::raw_ostream &OS = llvm::outs()) { - getSolverResults().dumpResults(*ICF, IDEProblem, OS); + getSolverResults().dumpResults(*ICF, OS); } void dumpAllInterPathEdges() { @@ -282,8 +276,8 @@ class IDESolver virtual void processCall(const PathEdge Edge) { PAMM_GET_INSTANCE; INC_COUNTER("Process Call", 1, Full); - PHASAR_LOG_LEVEL(DEBUG, "Process call at target: " - << IDEProblem.NtoString(Edge.getTarget())); + PHASAR_LOG_LEVEL(DEBUG, + "Process call at target: " << NToString(Edge.getTarget())); d_t d1 = Edge.factAtSource(); n_t n = Edge.getTarget(); // a call node; line 14... @@ -299,7 +293,7 @@ class IDESolver } PHASAR_LOG_LEVEL(DEBUG, "Possible return sites:"); for (auto ret : ReturnSiteNs) { - PHASAR_LOG_LEVEL(DEBUG, " " << IDEProblem.NtoString(ret)); + PHASAR_LOG_LEVEL(DEBUG, " " << NToString(ret)); }); // for each possible callee @@ -351,8 +345,8 @@ class IDESolver for (d_t d3 : Res) { using TableCell = typename Table>::Cell; // create initial self-loop - PHASAR_LOG_LEVEL(DEBUG, "Create initial self-loop with D: " - << IDEProblem.DtoString(d3)); + PHASAR_LOG_LEVEL( + DEBUG, "Create initial self-loop with D: " << DToString(d3)); WorkList.emplace_back(PathEdge(d3, SP, d3), EdgeIdentity{}); // line 15 // register the fact that has an incoming edge from @@ -363,8 +357,8 @@ class IDESolver // const std::set endSumm(endSummary(sP, d3)); // llvm::outs() << "ENDSUMM" << '\n'; // llvm::outs() << "Size: " << endSumm.size() << '\n'; - // llvm::outs() << "sP: " << IDEProblem.NtoString(sP) - // << "\nd3: " << IDEProblem.DtoString(d3) + // llvm::outs() << "sP: " << NToString(sP) + // << "\nd3: " << DToString(d3) // << '\n'; // printEndSummaryTab(); // still line 15.2 of Naeem/Lhotak/Rodriguez @@ -472,8 +466,8 @@ class IDESolver virtual void processNormalFlow(PathEdge Edge) { PAMM_GET_INSTANCE; INC_COUNTER("Process Normal", 1, Full); - PHASAR_LOG_LEVEL(DEBUG, "Process normal at target: " - << IDEProblem.NtoString(Edge.getTarget())); + PHASAR_LOG_LEVEL( + DEBUG, "Process normal at target: " << NToString(Edge.getTarget())); EdgeFunction f = jumpFunction(Edge); auto [d1, n, d2] = Edge.consume(); @@ -571,9 +565,9 @@ class IDESolver IF_LOG_ENABLED({ PHASAR_LOG_LEVEL(DEBUG, "Function : " << ICF->getFunctionOf(NHashN)->getName()); - PHASAR_LOG_LEVEL(DEBUG, "Inst. : " << IDEProblem.NtoString(NHashN)); - PHASAR_LOG_LEVEL(DEBUG, "Fact : " << IDEProblem.DtoString(NHashD)); - PHASAR_LOG_LEVEL(DEBUG, "Value : " << IDEProblem.LtoString(L)); + PHASAR_LOG_LEVEL(DEBUG, "Inst. : " << NToString(NHashN)); + PHASAR_LOG_LEVEL(DEBUG, "Fact : " << DToString(NHashD)); + PHASAR_LOG_LEVEL(DEBUG, "Value : " << LToString(L)); PHASAR_LOG_LEVEL(DEBUG, ' '); }); // TOP is the implicit default value which we do not need to store. @@ -588,12 +582,11 @@ class IDESolver EdgeFunction jumpFunction(const PathEdge Edge) { IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "JumpFunctions Forward-Lookup:"); - PHASAR_LOG_LEVEL(DEBUG, " Source D: " << IDEProblem.DtoString( - Edge.factAtSource())); - PHASAR_LOG_LEVEL( - DEBUG, " Target N: " << IDEProblem.NtoString(Edge.getTarget())); - PHASAR_LOG_LEVEL(DEBUG, " Target D: " << IDEProblem.DtoString( - Edge.factAtTarget()))); + PHASAR_LOG_LEVEL(DEBUG, + " Source D: " << DToString(Edge.factAtSource())); + PHASAR_LOG_LEVEL(DEBUG, " Target N: " << NToString(Edge.getTarget())); + PHASAR_LOG_LEVEL(DEBUG, + " Target D: " << DToString(Edge.factAtTarget()))); auto FwdLookupRes = JumpFn->forwardLookup(Edge.factAtSource(), Edge.getTarget()); @@ -632,15 +625,12 @@ class IDESolver << ". Path Edge --------------------------------------------"); PHASAR_LOG_LEVEL(DEBUG, ' '); PHASAR_LOG_LEVEL(DEBUG, "Process " << PathEdgeCount << ". path edge:"); - PHASAR_LOG_LEVEL(DEBUG, "< D source: " - << IDEProblem.DtoString(Edge.factAtSource()) - << " ;"); - PHASAR_LOG_LEVEL(DEBUG, " N target: " - << IDEProblem.NtoString(Edge.getTarget()) - << " ;"); - PHASAR_LOG_LEVEL(DEBUG, " D target: " - << IDEProblem.DtoString(Edge.factAtTarget()) - << " >"); + PHASAR_LOG_LEVEL(DEBUG, "< D source: " << DToString(Edge.factAtSource()) + << " ;"); + PHASAR_LOG_LEVEL(DEBUG, + " N target: " << NToString(Edge.getTarget()) << " ;"); + PHASAR_LOG_LEVEL(DEBUG, " D target: " << DToString(Edge.factAtTarget()) + << " >"); PHASAR_LOG_LEVEL(DEBUG, ' ')); if (!ICF->isCallSite(Edge.getTarget())) { @@ -717,11 +707,10 @@ class IDESolver // do processing for (const auto &[StartPoint, Facts] : AllSeeds) { for (auto &[Fact, Value] : Facts) { - PHASAR_LOG_LEVEL(DEBUG, - "set initial seed at: " - << IDEProblem.NtoString(StartPoint) - << ", fact: " << IDEProblem.DtoString(Fact) - << ", value: " << IDEProblem.LtoString(Value)); + PHASAR_LOG_LEVEL(DEBUG, "set initial seed at: " + << NToString(StartPoint) + << ", fact: " << DToString(Fact) + << ", value: " << LToString(Value)); // initialize the initial seeds with the top element as we have no // information at the beginning of the value computation problem setVal(StartPoint, Fact, Value); @@ -762,7 +751,7 @@ class IDESolver // Add zero value if it's not in the set of facts. PHASAR_LOG_LEVEL( DEBUG, "Zero-Value has been added automatically to start point: " - << IDEProblem.NtoString(StartPoint)); + << NToString(StartPoint)); Seeds.addSeed(StartPoint, ZeroValue, IDEProblem.bottomElement()); } } @@ -770,22 +759,20 @@ class IDESolver "Number of initial seeds: " << Seeds.countInitialSeeds()); PHASAR_LOG_LEVEL(DEBUG, "List of initial seeds: "); for (const auto &[StartPoint, Facts] : Seeds.getSeeds()) { - PHASAR_LOG_LEVEL(DEBUG, - "Start point: " << IDEProblem.NtoString(StartPoint)); + PHASAR_LOG_LEVEL(DEBUG, "Start point: " << NToString(StartPoint)); /// If statically disabling the logger, Fact and Value are unused. To /// prevent the copilation to fail with -Werror, add the [[maybe_unused]] /// attribute for ([[maybe_unused]] const auto &[Fact, Value] : Facts) { - PHASAR_LOG_LEVEL(DEBUG, "\tFact: " << IDEProblem.DtoString(Fact)); - PHASAR_LOG_LEVEL(DEBUG, "\tValue: " << IDEProblem.LtoString(Value)); + PHASAR_LOG_LEVEL(DEBUG, "\tFact: " << DToString(Fact)); + PHASAR_LOG_LEVEL(DEBUG, "\tValue: " << LToString(Value)); } } for (const auto &[StartPoint, Facts] : Seeds.getSeeds()) { for (const auto &[Fact, Value] : Facts) { - PHASAR_LOG_LEVEL( - DEBUG, "Submit seed at: " << IDEProblem.NtoString(StartPoint)); - PHASAR_LOG_LEVEL(DEBUG, "\tFact: " << IDEProblem.DtoString(Fact)); - PHASAR_LOG_LEVEL(DEBUG, "\tValue: " << IDEProblem.LtoString(Value)); + PHASAR_LOG_LEVEL(DEBUG, "Submit seed at: " << NToString(StartPoint)); + PHASAR_LOG_LEVEL(DEBUG, "\tFact: " << DToString(Fact)); + PHASAR_LOG_LEVEL(DEBUG, "\tValue: " << LToString(Value)); if (!IDEProblem.isZeroValue(Fact)) { INC_COUNTER("Gen facts", 1, Core); } @@ -806,8 +793,8 @@ class IDESolver virtual void processExit(const PathEdge Edge) { PAMM_GET_INSTANCE; INC_COUNTER("Process Exit", 1, Full); - PHASAR_LOG_LEVEL(DEBUG, "Process exit at target: " - << IDEProblem.NtoString(Edge.getTarget())); + PHASAR_LOG_LEVEL(DEBUG, + "Process exit at target: " << NToString(Edge.getTarget())); n_t n = Edge.getTarget(); // an exit node; line 21... EdgeFunction f = jumpFunction(Edge); f_t FunctionThatNeedsSummary = ICF->getFunctionOf(n); @@ -1054,11 +1041,9 @@ class IDESolver void propagate(d_t SourceVal, n_t Target, d_t TargetVal, EdgeFunction f) { PHASAR_LOG_LEVEL(DEBUG, "Propagate flow"); - PHASAR_LOG_LEVEL(DEBUG, - "Source value : " << IDEProblem.DtoString(SourceVal)); - PHASAR_LOG_LEVEL(DEBUG, "Target : " << IDEProblem.NtoString(Target)); - PHASAR_LOG_LEVEL(DEBUG, - "Target value : " << IDEProblem.DtoString(TargetVal)); + PHASAR_LOG_LEVEL(DEBUG, "Source value : " << DToString(SourceVal)); + PHASAR_LOG_LEVEL(DEBUG, "Target : " << NToString(Target)); + PHASAR_LOG_LEVEL(DEBUG, "Target value : " << DToString(TargetVal)); PHASAR_LOG_LEVEL( DEBUG, "Edge function : " << f << " (result of previous compose)"); @@ -1095,13 +1080,11 @@ class IDESolver pathEdgeProcessingTask(std::move(Edge)); IF_LOG_ENABLED(if (!IDEProblem.isZeroValue(TargetVal)) { - PHASAR_LOG_LEVEL( - DEBUG, "EDGE: getFunction()->getName() << ", D: " - << IDEProblem.DtoString(SourceVal) << '>'); - PHASAR_LOG_LEVEL(DEBUG, - " ---> getFunction()->getName() + << ", D: " << DToString(SourceVal) + << '>'); + PHASAR_LOG_LEVEL(DEBUG, " ---> '); PHASAR_LOG_LEVEL(DEBUG, ' '); }); @@ -1141,15 +1124,12 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "Start of incomingtab entry"); for (const auto &Cell : IncomingTab.cellSet()) { - PHASAR_LOG_LEVEL(DEBUG, - "sP: " << IDEProblem.NtoString(Cell.getRowKey())); - PHASAR_LOG_LEVEL(DEBUG, - "d3: " << IDEProblem.DtoString(Cell.getColumnKey())); + PHASAR_LOG_LEVEL(DEBUG, "sP: " << NToString(Cell.getRowKey())); + PHASAR_LOG_LEVEL(DEBUG, "d3: " << DToString(Cell.getColumnKey())); for (const auto &Entry : Cell.getValue()) { - PHASAR_LOG_LEVEL(DEBUG, - " n: " << IDEProblem.NtoString(Entry.first)); + PHASAR_LOG_LEVEL(DEBUG, " n: " << NToString(Entry.first)); for (const auto &Fact : Entry.second) { - PHASAR_LOG_LEVEL(DEBUG, " d2: " << IDEProblem.DtoString(Fact)); + PHASAR_LOG_LEVEL(DEBUG, " d2: " << DToString(Fact)); } } PHASAR_LOG_LEVEL(DEBUG, "---------------"); @@ -1160,19 +1140,19 @@ class IDESolver IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Start of endsummarytab entry"); - EndsummaryTab.foreachCell([this](const auto &Row, const auto &Col, - const auto &Val) { - PHASAR_LOG_LEVEL(DEBUG, "sP: " << IDEProblem.NtoString(Row)); - PHASAR_LOG_LEVEL(DEBUG, "d1: " << IDEProblem.DtoString(Col)); + EndsummaryTab.foreachCell( + [](const auto &Row, const auto &Col, const auto &Val) { + PHASAR_LOG_LEVEL(DEBUG, "sP: " << NToString(Row)); + PHASAR_LOG_LEVEL(DEBUG, "d1: " << DToString(Col)); - Val.foreachCell([this](const auto &InnerRow, const auto &InnerCol, + Val.foreachCell([](const auto &InnerRow, const auto &InnerCol, const auto &InnerVal) { - PHASAR_LOG_LEVEL(DEBUG, " eP: " << IDEProblem.NtoString(InnerRow)); - PHASAR_LOG_LEVEL(DEBUG, " d2: " << IDEProblem.DtoString(InnerCol)); - PHASAR_LOG_LEVEL(DEBUG, " EF: " << InnerVal); - }); - PHASAR_LOG_LEVEL(DEBUG, "---------------"); - }); + PHASAR_LOG_LEVEL(DEBUG, " eP: " << NToString(InnerRow)); + PHASAR_LOG_LEVEL(DEBUG, " d2: " << DToString(InnerCol)); + PHASAR_LOG_LEVEL(DEBUG, " EF: " << InnerVal); + }); + PHASAR_LOG_LEVEL(DEBUG, "---------------"); + }); PHASAR_LOG_LEVEL(DEBUG, "End of endsummarytab entry");) } @@ -1193,15 +1173,15 @@ class IDESolver }); for (const auto &Cell : Cells) { auto Edge = std::make_pair(Cell.getRowKey(), Cell.getColumnKey()); - std::string N2Label = IDEProblem.NtoString(Edge.second); - llvm::outs() << "\nN1: " << IDEProblem.NtoString(Edge.first) << '\n' + std::string N2Label = NToString(Edge.second); + llvm::outs() << "\nN1: " << NToString(Edge.first) << '\n' << "N2: " << N2Label << "\n----" << std::string(N2Label.size(), '-') << '\n'; for (auto D1ToD2Set : Cell.getValue()) { auto D1Fact = D1ToD2Set.first; - llvm::outs() << "D1: " << IDEProblem.DtoString(D1Fact) << '\n'; + llvm::outs() << "D1: " << DToString(D1Fact) << '\n'; for (auto D2Fact : D1ToD2Set.second) { - llvm::outs() << "\tD2: " << IDEProblem.DtoString(D2Fact) << '\n'; + llvm::outs() << "\tD2: " << DToString(D2Fact) << '\n'; } llvm::outs() << '\n'; } @@ -1221,15 +1201,15 @@ class IDESolver }); for (const auto &Cell : Cells) { auto Edge = std::make_pair(Cell.getRowKey(), Cell.getColumnKey()); - std::string N2Label = IDEProblem.NtoString(Edge.second); - llvm::outs() << "\nN1: " << IDEProblem.NtoString(Edge.first) << '\n' + std::string N2Label = NToString(Edge.second); + llvm::outs() << "\nN1: " << NToString(Edge.first) << '\n' << "N2: " << N2Label << "\n----" << std::string(N2Label.size(), '-') << '\n'; for (auto D1ToD2Set : Cell.getValue()) { auto D1Fact = D1ToD2Set.first; - llvm::outs() << "D1: " << IDEProblem.DtoString(D1Fact) << '\n'; + llvm::outs() << "D1: " << DToString(D1Fact) << '\n'; for (auto D2Fact : D1ToD2Set.second) { - llvm::outs() << "\tD2: " << IDEProblem.DtoString(D2Fact) << '\n'; + llvm::outs() << "\tD2: " << DToString(D2Fact) << '\n'; } llvm::outs() << '\n'; } @@ -1264,10 +1244,10 @@ class IDESolver // Case 2: d1 not in d2-Set, i.e., d1 was killed. d2-Set could be empty. for (const auto &Cell : ComputedIntraPathEdges.cellSet()) { auto Edge = std::make_pair(Cell.getRowKey(), Cell.getColumnKey()); - PHASAR_LOG_LEVEL(DEBUG, "N1: " << IDEProblem.NtoString(Edge.first)); - PHASAR_LOG_LEVEL(DEBUG, "N2: " << IDEProblem.NtoString(Edge.second)); + PHASAR_LOG_LEVEL(DEBUG, "N1: " << NToString(Edge.first)); + PHASAR_LOG_LEVEL(DEBUG, "N2: " << NToString(Edge.second)); for (auto &[D1, D2s] : Cell.getValue()) { - PHASAR_LOG_LEVEL(DEBUG, "d1: " << IDEProblem.DtoString(D1)); + PHASAR_LOG_LEVEL(DEBUG, "d1: " << DToString(D1)); NumIntraPathEdges += D2s.size(); // Case 1 if (D2s.find(D1) != D2s.end()) { @@ -1283,7 +1263,7 @@ class IDESolver } IF_LOG_ENABLED([this](const auto &D2s) { for (auto D2 : D2s) { - PHASAR_LOG_LEVEL(DEBUG, "d2: " << IDEProblem.DtoString(D2)); + PHASAR_LOG_LEVEL(DEBUG, "d2: " << DToString(D2)); } PHASAR_LOG_LEVEL(DEBUG, "----"); }(D2s)); @@ -1296,8 +1276,8 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "INTER PATH EDGES"); for (const auto &Cell : ComputedInterPathEdges.cellSet()) { auto Edge = std::make_pair(Cell.getRowKey(), Cell.getColumnKey()); - PHASAR_LOG_LEVEL(DEBUG, "N1: " << IDEProblem.NtoString(Edge.first)); - PHASAR_LOG_LEVEL(DEBUG, "N2: " << IDEProblem.NtoString(Edge.second)); + PHASAR_LOG_LEVEL(DEBUG, "N1: " << NToString(Edge.first)); + PHASAR_LOG_LEVEL(DEBUG, "N2: " << NToString(Edge.second)); // --- Call-flow Path Edges --- // Case 1: d1 --> empty set // Can be ignored, since killing a fact in the caller context will @@ -1314,7 +1294,7 @@ class IDESolver // Process the summary's #gen and #kill. if (ICF->isCallSite(Edge.first)) { for (auto &[D1, D2s] : Cell.getValue()) { - PHASAR_LOG_LEVEL(DEBUG, "d1: " << IDEProblem.DtoString(D1)); + PHASAR_LOG_LEVEL(DEBUG, "d1: " << DToString(D1)); NumInterPathEdges += D2s.size(); for (auto D2 : D2s) { if (!IDEProblem.isZeroValue(D2)) { @@ -1340,7 +1320,7 @@ class IDESolver } else { ProcessSummaryFacts.emplace(Edge.second, D2); } - PHASAR_LOG_LEVEL(DEBUG, "d2: " << IDEProblem.DtoString(D2)); + PHASAR_LOG_LEVEL(DEBUG, "d2: " << DToString(D2)); } PHASAR_LOG_LEVEL(DEBUG, "----"); } @@ -1354,7 +1334,7 @@ class IDESolver // Zero value does not count towards generated/killed facts. if (ICF->isExitInst(Cell.getRowKey())) { for (auto &[D1, D2s] : Cell.getValue()) { - PHASAR_LOG_LEVEL(DEBUG, "d1: " << IDEProblem.DtoString(D1)); + PHASAR_LOG_LEVEL(DEBUG, "d1: " << DToString(D1)); NumInterPathEdges += D2s.size(); auto CallerFacts = ValidInCallerContext[Edge.second]; for (auto D2 : D2s) { @@ -1362,7 +1342,7 @@ class IDESolver if (CallerFacts.find(D2) == CallerFacts.end()) { NumGenFacts++; } - PHASAR_LOG_LEVEL(DEBUG, "d2: " << IDEProblem.DtoString(D2)); + PHASAR_LOG_LEVEL(DEBUG, "d2: " << DToString(D2)); } PHASAR_LOG_LEVEL(DEBUG, "----"); } @@ -1372,10 +1352,8 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "SUMMARY REUSE"); std::size_t TotalSummaryReuse = 0; for (const auto &Entry : FSummaryReuse) { - PHASAR_LOG_LEVEL(DEBUG, - "N1: " << IDEProblem.NtoString(Entry.first.first)); - PHASAR_LOG_LEVEL(DEBUG, - "D1: " << IDEProblem.DtoString(Entry.first.second)); + PHASAR_LOG_LEVEL(DEBUG, "N1: " << NToString(Entry.first.first)); + PHASAR_LOG_LEVEL(DEBUG, "D1: " << DToString(Entry.first.second)); PHASAR_LOG_LEVEL(DEBUG, "#Reuse: " << Entry.second); TotalSummaryReuse += Entry.second; } @@ -1438,8 +1416,8 @@ class IDESolver }); for (const auto &Cell : Cells) { auto Edge = std::make_pair(Cell.getRowKey(), Cell.getColumnKey()); - std::string N1Label = IDEProblem.NtoString(Edge.first); - std::string N2Label = IDEProblem.NtoString(Edge.second); + std::string N1Label = NToString(Edge.first); + std::string N2Label = NToString(Edge.second); PHASAR_LOG_LEVEL(DEBUG, "N1: " << N1Label); PHASAR_LOG_LEVEL(DEBUG, "N2: " << N2Label); std::string N1StmtId = ICF->getStatementId(Edge.first); @@ -1468,7 +1446,7 @@ class IDESolver unsigned D2FactId = 0; for (const auto &D1ToD2Set : Cell.getValue()) { auto D1Fact = D1ToD2Set.first; - PHASAR_LOG_LEVEL(DEBUG, "d1: " << IDEProblem.DtoString(D1Fact)); + PHASAR_LOG_LEVEL(DEBUG, "d1: " << DToString(D1Fact)); DOTNode D1; if (IDEProblem.isZeroValue(D1Fact)) { @@ -1477,7 +1455,7 @@ class IDESolver } else { // Get the fact-ID D1FactId = G.getFactID(D1Fact); - std::string D1Label = IDEProblem.DtoString(D1Fact); + std::string D1Label = DToString(D1Fact); // Get or create the fact subgraph D1FSG = FG->getOrCreateFactSG(D1FactId, D1Label); @@ -1489,13 +1467,13 @@ class IDESolver DOTFactSubGraph *D2FSG = nullptr; for (const auto &D2Fact : D1ToD2Set.second) { - PHASAR_LOG_LEVEL(DEBUG, "d2: " << IDEProblem.DtoString(D2Fact)); + PHASAR_LOG_LEVEL(DEBUG, "d2: " << DToString(D2Fact)); // We do not need to generate any intra-procedural nodes and edges // for the zero value since they will be auto-generated if (!IDEProblem.isZeroValue(D2Fact)) { // Get the fact-ID D2FactId = G.getFactID(D2Fact); - std::string D2Label = IDEProblem.DtoString(D2Fact); + std::string D2Label = DToString(D2Fact); DOTNode D2 = {FuncName, D2Label, N2StmtId, D2FactId, false, true}; std::string EFLabel; auto EFVec = IntermediateEdgeFunctions[std::make_tuple( @@ -1531,8 +1509,8 @@ class IDESolver }); for (const auto &Cell : Cells) { auto Edge = std::make_pair(Cell.getRowKey(), Cell.getColumnKey()); - std::string N1Label = IDEProblem.NtoString(Edge.first); - std::string N2Label = IDEProblem.NtoString(Edge.second); + std::string N1Label = NToString(Edge.first); + std::string N2Label = NToString(Edge.second); std::string FNameOfN1 = ICF->getFunctionOf(Edge.first)->getName().str(); std::string FNameOfN2 = ICF->getFunctionOf(Edge.second)->getName().str(); std::string N1StmtId = ICF->getStatementId(Edge.first); @@ -1573,14 +1551,14 @@ class IDESolver unsigned D2FactId = 0; for (const auto &D1ToD2Set : Cell.getValue()) { auto D1Fact = D1ToD2Set.first; - PHASAR_LOG_LEVEL(DEBUG, "d1: " << IDEProblem.DtoString(D1Fact)); + PHASAR_LOG_LEVEL(DEBUG, "d1: " << DToString(D1Fact)); DOTNode D1; if (IDEProblem.isZeroValue(D1Fact)) { D1 = {FNameOfN1, "Λ", N1StmtId, 0, false, true}; } else { // Get the fact-ID D1FactId = G.getFactID(D1Fact); - std::string D1Label = IDEProblem.DtoString(D1Fact); + std::string D1Label = DToString(D1Fact); D1 = {FNameOfN1, D1Label, N1StmtId, D1FactId, false, true}; // FG should already exist even for single statement functions if (!G.containsFactSG(FNameOfN1, D1FactId)) { @@ -1592,14 +1570,14 @@ class IDESolver auto D2Set = D1ToD2Set.second; for (const auto &D2Fact : D2Set) { - PHASAR_LOG_LEVEL(DEBUG, "d2: " << IDEProblem.DtoString(D2Fact)); + PHASAR_LOG_LEVEL(DEBUG, "d2: " << DToString(D2Fact)); DOTNode D2; if (IDEProblem.isZeroValue(D2Fact)) { D2 = {FNameOfN2, "Λ", N2StmtId, 0, false, true}; } else { // Get the fact-ID D2FactId = G.getFactID(D2Fact); - std::string D2Label = IDEProblem.DtoString(D2Fact); + std::string D2Label = DToString(D2Fact); D2 = {FNameOfN2, D2Label, N2StmtId, D2FactId, false, true}; // FG should already exist even for single statement functions if (!G.containsFactSG(FNameOfN2, D2FactId)) { diff --git a/include/phasar/DataFlow/IfdsIde/Solver/JumpFunctions.h b/include/phasar/DataFlow/IfdsIde/Solver/JumpFunctions.h index 6bb2c6ffa5..0a9bcb3274 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/JumpFunctions.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/JumpFunctions.h @@ -17,7 +17,7 @@ #ifndef PHASAR_DATAFLOW_IFDSIDE_SOLVER_JUMPFUNCTIONS_H #define PHASAR_DATAFLOW_IFDSIDE_SOLVER_JUMPFUNCTIONS_H -#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" +#include "phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/Table.h" @@ -43,9 +43,6 @@ template class JumpFunctions { using d_t = typename AnalysisDomainTy::d_t; using n_t = typename AnalysisDomainTy::n_t; -private: - const IDETabulationProblem &Problem; - protected: // mapping from target node and value to a list of all source values and // associated functions where the list is implemented as a mapping from @@ -64,10 +61,7 @@ template class JumpFunctions { NonEmptyLookupByTargetNode; public: - JumpFunctions( - const IDETabulationProblem &Problem) - : Problem(Problem) {} - + JumpFunctions() noexcept = default; ~JumpFunctions() = default; JumpFunctions(const JumpFunctions &JFs) = default; @@ -82,11 +76,9 @@ template class JumpFunctions { void addFunction(d_t SourceVal, n_t Target, d_t TargetVal, EdgeFunction EdgeFunc) { PHASAR_LOG_LEVEL(DEBUG, "Start adding new jump function"); - PHASAR_LOG_LEVEL(DEBUG, - "Fact at source : " << Problem.DtoString(SourceVal)); - PHASAR_LOG_LEVEL(DEBUG, - "Fact at target : " << Problem.DtoString(TargetVal)); - PHASAR_LOG_LEVEL(DEBUG, "Destination : " << Problem.NtoString(Target)); + PHASAR_LOG_LEVEL(DEBUG, "Fact at source : " << DToString(SourceVal)); + PHASAR_LOG_LEVEL(DEBUG, "Fact at target : " << DToString(TargetVal)); + PHASAR_LOG_LEVEL(DEBUG, "Destination : " << NToString(Target)); PHASAR_LOG_LEVEL(DEBUG, "Edge Function : " << EdgeFunc); // we do not store the default function (all-top) if (llvm::isa>(EdgeFunc)) { @@ -207,12 +199,12 @@ template class JumpFunctions { OS << "\n* Print all Jump Functions *"; OS << "\n******************************************************\n"; for (auto &Entry : NonEmptyLookupByTargetNode) { - std::string NLabel = Problem.NtoString(Entry.first); + std::string NLabel = NToString(Entry.first); OS << "\nN: " << NLabel << "\n---" << std::string(NLabel.size(), '-') << '\n'; for (auto Cell : Entry.second.cellSet()) { - OS << "D1: " << Problem.DtoString(Cell.r) << '\n' - << "\tD2: " << Problem.DtoString(Cell.c) << '\n' + OS << "D1: " << DToString(Cell.r) << '\n' + << "\tD2: " << DToString(Cell.c) << '\n' << "\tEF: " << Cell.v << "\n\n"; } } @@ -223,11 +215,11 @@ template class JumpFunctions { "EdgeFunctionPtrType>>\n"; auto CellVec = NonEmptyReverseLookup.cellVec(); for (auto Cell : CellVec) { - OS << "N : " << Problem.NtoString(Cell.r) - << "\nD1: " << Problem.DtoString(Cell.c) << '\n'; + OS << "N : " << NToString(Cell.r) << "\nD1: " << DToString(Cell.c) + << '\n'; for (auto D2ToEF : Cell.v) { - OS << "D2: " << Problem.DtoString(D2ToEF.first) - << "\nEF: " << D2ToEF.second << '\n'; + OS << "D2: " << DToString(D2ToEF.first) << "\nEF: " << D2ToEF.second + << '\n'; } OS << '\n'; } @@ -238,11 +230,11 @@ template class JumpFunctions { "EdgeFunctionPtrType>>\n"; auto CellVec = NonEmptyForwardLookup.cellVec(); for (auto Cell : CellVec) { - OS << "D1: " << Problem.DtoString(Cell.r) - << "\nN : " << Problem.NtoString(Cell.c) << '\n'; + OS << "D1: " << DToString(Cell.r) << "\nN : " << NToString(Cell.c) + << '\n'; for (auto D2ToEF : Cell.v) { - OS << "D2: " << Problem.DtoString(D2ToEF.first) - << "\nEF: " << D2ToEF.second << '\n'; + OS << "D2: " << DToString(D2ToEF.first) << "\nEF: " << D2ToEF.second + << '\n'; } OS << '\n'; } @@ -252,13 +244,12 @@ template class JumpFunctions { OS << "DUMP nonEmptyLookupByTargetNode\nstd::unordered_map>\n"; for (auto Node : NonEmptyLookupByTargetNode) { - OS << "\nN : " << Problem.NtoString(Node.first) << '\n'; + OS << "\nN : " << NToString(Node.first) << '\n'; auto Table = NonEmptyLookupByTargetNode[Node.first]; auto CellVec = Table.cellVec(); for (auto Cell : CellVec) { - OS << "D1: " << Problem.DtoString(Cell.r) - << "\nD2: " << Problem.DtoString(Cell.c) << "\nEF: " << Cell.v - << '\n'; + OS << "D1: " << DToString(Cell.r) << "\nD2: " << DToString(Cell.c) + << "\nEF: " << Cell.v << '\n'; } OS << '\n'; } diff --git a/include/phasar/DataFlow/IfdsIde/SolverResults.h b/include/phasar/DataFlow/IfdsIde/SolverResults.h index 780f1ea6fb..512d80063f 100644 --- a/include/phasar/DataFlow/IfdsIde/SolverResults.h +++ b/include/phasar/DataFlow/IfdsIde/SolverResults.h @@ -131,9 +131,7 @@ class SolverResultsBase { } template - void dumpResults(const ICFGTy &ICF, const NodePrinterBase &NP, - const DataFlowFactPrinterBase &DP, - const EdgeFactPrinterBase &LP, + void dumpResults(const ICFGTy &ICF, llvm::raw_ostream &OS = llvm::outs()) const { using f_t = typename ICFGTy::f_t; @@ -170,24 +168,18 @@ class SolverResultsBase { } if (Prev != Curr) { Prev = Curr; - std::string NString = NP.NtoString(Curr); + std::string NString = NToString(Curr); std::string Line(NString.size(), '-'); OS << "\n\nN: " << NString << "\n---" << Line << '\n'; } - OS << "\tD: " << DP.DtoString(Cells[I].getColumnKey()) - << " | V: " << LP.LtoString(Cells[I].getValue()) << '\n'; + OS << "\tD: " << DToString(Cells[I].getColumnKey()) + << " | V: " << LToString(Cells[I].getValue()) << '\n'; } } OS << '\n'; STOP_TIMER("DFA IDE Result Dumping", Full); } - template - void dumpResults(const ICFGTy &ICF, const ProblemTy &IDEProblem, - llvm::raw_ostream &OS = llvm::outs()) const { - dumpResults(ICF, IDEProblem, IDEProblem, IDEProblem, OS); - } - private: [[nodiscard]] const Derived &self() const noexcept { static_assert(std::is_base_of_v); diff --git a/include/phasar/DataFlow/Mono/Contexts/CallStringCTX.h b/include/phasar/DataFlow/Mono/Contexts/CallStringCTX.h index ae813f39f2..2e835c6f56 100644 --- a/include/phasar/DataFlow/Mono/Contexts/CallStringCTX.h +++ b/include/phasar/DataFlow/Mono/Contexts/CallStringCTX.h @@ -68,11 +68,10 @@ template class CallStringCTX { return Lhs.cs < Rhs.cs; } - llvm::raw_ostream &print(llvm::raw_ostream &OS, - const NodePrinterBase &NP) const { + llvm::raw_ostream &print(llvm::raw_ostream &OS) const { OS << "Call string: [ "; for (auto C : CallString) { - NP.printNode(OS, C); + OS << NToString(C); if (C != CallString.back()) { OS << " * "; } diff --git a/include/phasar/DataFlow/Mono/IntraMonoProblem.h b/include/phasar/DataFlow/Mono/IntraMonoProblem.h index 8405d20304..4915cfe4f9 100644 --- a/include/phasar/DataFlow/Mono/IntraMonoProblem.h +++ b/include/phasar/DataFlow/Mono/IntraMonoProblem.h @@ -35,10 +35,7 @@ struct HasNoConfigurationType; template class TypeHierarchy; template class CFG; -template -class IntraMonoProblem : public NodePrinter, - public DataFlowFactPrinter, - public FunctionPrinter { +template class IntraMonoProblem { public: using n_t = typename AnalysisDomainTy::n_t; using d_t = typename AnalysisDomainTy::d_t; @@ -72,7 +69,7 @@ class IntraMonoProblem : public NodePrinter, : IRDB(IRDB), TH(TH), CF(CF), PT(PT), EntryPoints(std::move(EntryPoints)) {} - ~IntraMonoProblem() override = default; + virtual ~IntraMonoProblem() = default; virtual mono_container_t normalFlow(n_t Inst, const mono_container_t &In) = 0; diff --git a/include/phasar/DataFlow/Mono/Solver/InterMonoSolver.h b/include/phasar/DataFlow/Mono/Solver/InterMonoSolver.h index b8785ebe0d..518d80c7d8 100644 --- a/include/phasar/DataFlow/Mono/Solver/InterMonoSolver.h +++ b/include/phasar/DataFlow/Mono/Solver/InterMonoSolver.h @@ -85,8 +85,7 @@ template class InterMonoSolver { void printWorkList() { llvm::outs() << "CURRENT WORKLIST:\n"; for (auto &[Src, Dst] : Worklist) { - llvm::outs() << IMProblem.NtoString(Src) << " --> " - << IMProblem.NtoString(Dst) << '\n'; + llvm::outs() << NToString(Src) << " --> " << NToString(Dst) << '\n'; } llvm::outs() << "-----------------\n"; } @@ -178,8 +177,8 @@ template class InterMonoSolver { llvm::outs() << "Handle normal flow\n"; auto Src = Edge.first; auto Dst = Edge.second; - llvm::outs() << "Src: " << IMProblem.NtoString(Src) << '\n'; - llvm::outs() << "Dst: " << IMProblem.NtoString(Dst) << '\n'; + llvm::outs() << "Src: " << NToString(Src) << '\n'; + llvm::outs() << "Dst: " << NToString(Dst) << '\n'; std::unordered_map, mono_container_t> Out; for (auto &[Ctx, Facts] : Analysis[Src]) { Out[Ctx] = IMProblem.normalFlow(Src, Analysis[Src][Ctx]); @@ -224,8 +223,8 @@ template class InterMonoSolver { std::unordered_map, mono_container_t> Out; if (!isIntraEdge(Edge)) { llvm::outs() << "Handle call flow\n"; - llvm::outs() << "Src: " << IMProblem.NtoString(Src) << '\n'; - llvm::outs() << "Dst: " << IMProblem.NtoString(Dst) << '\n'; + llvm::outs() << "Src: " << NToString(Src) << '\n'; + llvm::outs() << "Dst: " << NToString(Dst) << '\n'; for (auto &[Ctx, Facts] : Analysis[Src]) { auto CTXAdd(Ctx); CTXAdd.push_back(Src); @@ -253,8 +252,8 @@ template class InterMonoSolver { } else { // Handle call-to-ret flow llvm::outs() << "Handle call to ret flow\n"; - llvm::outs() << "Src: " << IMProblem.NtoString(Src) << '\n'; - llvm::outs() << "Dst: " << IMProblem.NtoString(Dst) << '\n'; + llvm::outs() << "Src: " << NToString(Src) << '\n'; + llvm::outs() << "Dst: " << NToString(Dst) << '\n'; for (auto &[Ctx, Facts] : Analysis[Src]) { // call-to-ret flow does not modify contexts Out[Ctx] = IMProblem.callToRetFlow( @@ -288,11 +287,11 @@ template class InterMonoSolver { std::unordered_map, mono_container_t> Out; llvm::outs() << "\nHandle ret flow in: " << ICF->getFunctionName(ICF->getFunctionOf(Src)) << '\n'; - llvm::outs() << "Src: " << IMProblem.NtoString(Src) << '\n'; - llvm::outs() << "Dst: " << IMProblem.NtoString(Dst) << '\n'; + llvm::outs() << "Src: " << NToString(Src) << '\n'; + llvm::outs() << "Dst: " << NToString(Dst) << '\n'; for (auto &[Ctx, Facts] : Analysis[Src]) { auto CTXRm(Ctx); - CTXRm.print(llvm::outs() << "CTXRm: ", IMProblem) << '\n'; + CTXRm.print(llvm::outs() << "CTXRm: ") << '\n'; // we need to use several call- and retsites if the context is empty llvm::SmallVector CallSites; @@ -319,7 +318,7 @@ template class InterMonoSolver { // TODO! llvm::outs() << "ResSites.size(): " << RetSites.size() << '\n'; for (auto RetSite : RetSites) { - llvm::outs() << "RetSite: " << IMProblem.NtoString(RetSite) << '\n'; + llvm::outs() << "RetSite: " << NToString(RetSite) << '\n'; llvm::outs() << "Return facts: "; IMProblem.printContainer(llvm::outs(), Out[CTXRm]); llvm::outs() << '\n'; @@ -402,19 +401,17 @@ template class InterMonoSolver { virtual void dumpResults(llvm::raw_ostream &OS = llvm::outs()) { OS << "======= DUMP LLVM-INTER-MONOTONE-SOLVER RESULTS =======\n"; for (auto &[Node, ContextMap] : this->Analysis) { - OS << "Instruction:\n" << IMProblem.NtoString(Node); + OS << "Instruction:\n" << NToString(Node); OS << "\nFacts:\n"; if (ContextMap.empty()) { OS << "\tEMPTY\n"; } else { for (auto &[Context, FlowFacts] : ContextMap) { - Context.print(OS, IMProblem) << '\n'; + Context.print(OS) << '\n'; if (FlowFacts.empty()) { OS << "\tEMPTY\n"; } else { - for (auto FlowFact : FlowFacts) { - OS << IMProblem.DtoString(FlowFact); - } + IMProblem.printContainer(OS, FlowFacts); } } } diff --git a/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h b/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h index 53c26627c9..ac46b90687 100644 --- a/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h +++ b/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h @@ -115,14 +115,12 @@ template class IntraMonoSolver { OS << "Intra-Monotone solver results:\n" "------------------------------\n"; for (auto &[Node, FlowFacts] : this->Analysis) { - OS << "Instruction:\n" << this->IMProblem.NtoString(Node); + OS << "Instruction:\n" << NToString(Node); OS << "\nFacts:\n"; if (FlowFacts.empty()) { OS << "\tEMPTY\n"; } else { - for (auto FlowFact : FlowFacts) { - OS << this->IMProblem.DtoString(FlowFact) << '\n'; - } + IMProblem.printContainer(OS, FlowFacts); } OS << "\n\n"; } diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h index 6aa8e7d11b..e7dceb8eb6 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h @@ -250,14 +250,6 @@ class IDEExtendedTaintAnalysis // Printing functions - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printEdgeFact(llvm::raw_ostream &OS, l_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override; - void emitTextReport(const SolverResults &SR, llvm::raw_ostream &OS = llvm::outs()) override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h index 2be5e7f2d8..edde5b462f 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h @@ -106,14 +106,6 @@ class IDEGeneralizedLCA : public IDETabulationProblem { EdgeFunction allTopFunction() override; - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - - void printEdgeFact(llvm::raw_ostream &OS, l_t L) const override; - // void printIDEReport(llvm::raw_ostream &OS, // SolverResults &SR) override; void emitTextReport(const SolverResults &SR, @@ -127,7 +119,6 @@ class IDEGeneralizedLCA : public IDETabulationProblem { void stripBottomResults(std::unordered_map &Res); [[nodiscard]] bool isEntryPoint(const std::string &Name) const; - template std::string VtoString(V Val); // NOLINT bool isStringConstructor(const llvm::Function *Func); }; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index e9ea1e2156..8f9a71af7d 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -1135,23 +1135,6 @@ class IDEInstInteractionAnalysisT // Provide functionalities for printing things and emitting text reports. - void printNode(llvm::raw_ostream &OS, n_t n) const override { - OS << llvmIRToString(n); - } - - void printDataFlowFact(llvm::raw_ostream &OS, d_t FlowFact) const override { - OS << llvmIRToString(FlowFact); - } - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override { - OS << Fun->getName(); - } - - inline void printEdgeFact(llvm::raw_ostream &OS, - l_t EdgeFact) const override { - printEdgeFactImpl(OS, EdgeFact); - } - static void stripBottomResults(std::unordered_map &Res) { for (auto It = Res.begin(); It != Res.end();) { if (It->second.isBottom()) { @@ -1178,11 +1161,11 @@ class IDEInstInteractionAnalysisT auto Results = SR.resultsAt(Inst, true); stripBottomResults(Results); if (!Results.empty()) { - OS << "At IR statement: " << this->NtoString(Inst) << '\n'; + OS << "At IR statement: " << NToString(Inst) << '\n'; for (auto Result : Results) { if (!Result.second.isBottom()) { - OS << " Fact: " << this->DtoString(Result.first) - << "\n Value: " << this->LtoString(Result.second) << '\n'; + OS << " Fact: " << DToString(Result.first) + << "\n Value: " << LToString(Result.second) << '\n'; } } OS << '\n'; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h index 7187e5d1b8..2e7c6d8737 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h @@ -119,14 +119,6 @@ class IDELinearConstantAnalysis // Helper functions - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - - void printEdgeFact(llvm::raw_ostream &OS, l_t L) const override; - [[nodiscard]] lca_results_t getLCAResults(SolverResults SR); void emitTextReport(const SolverResults &SR, diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h index 40254b0720..c4b9ab965c 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.h @@ -97,14 +97,6 @@ class IDEProtoAnalysis : public IDETabulationProblem { l_t join(l_t Lhs, l_t Rhs) override; EdgeFunction allTopFunction() override; - - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - - void printEdgeFact(llvm::raw_ostream &OS, l_t L) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h index 05e4aad308..81036cdbe0 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h @@ -11,6 +11,7 @@ #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IDESECUREHEAPPROPAGATION_H #include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h" #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "llvm/ADT/StringRef.h" @@ -82,12 +83,6 @@ class IDESecureHeapPropagation [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - // in addition provide specifications for the IDE parts EdgeFunction getNormalEdgeFunction(n_t Curr, d_t CurrNode, n_t Succ, @@ -110,11 +105,12 @@ class IDESecureHeapPropagation n_t RetSite, d_t RetSiteNode) override; - void printEdgeFact(llvm::raw_ostream &OS, l_t L) const override; - void emitTextReport(const SolverResults &SR, llvm::raw_ostream &OS) override; }; + +llvm::StringRef DToString(SecureHeapFact Fact) noexcept; +llvm::StringRef LToString(SecureHeapValue Val) noexcept; } // namespace psr #endif diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h index 494ddb8a5c..3c1736fb58 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.h @@ -98,14 +98,6 @@ class IDESolverTest : public IDETabulationProblem { l_t join(l_t Lhs, l_t Rhs) override; EdgeFunction allTopFunction() override; - - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - - void printEdgeFact(llvm::raw_ostream &OS, l_t L) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h index fe57965bf7..9335838f9c 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -10,38 +10,148 @@ #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IDETYPESTATEANALYSIS_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IDETYPESTATEANALYSIS_H +#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" +#include "phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h" +#include "phasar/DataFlow/IfdsIde/FlowFunctions.h" #include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.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 "llvm/IR/InstrTypes.h" +#include "phasar/Utils/ByRef.h" +#include "phasar/Utils/JoinLattice.h" +#include "phasar/Utils/Logger.h" +#include "phasar/Utils/Printer.h" +#include "phasar/Utils/TypeTraits.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Demangle/Demangle.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Value.h" #include #include #include +#include #include -namespace llvm { -class CallBase; -class Instruction; -class Function; -class Value; -} // namespace llvm - namespace psr { class LLVMBasedICFG; class LLVMTypeHierarchy; -struct TypeStateDescription; +namespace detail { + +class IDETypeStateAnalysisBaseCommon : public LLVMAnalysisDomainDefault { +public: + using container_type = std::set; + using FlowFunctionPtrType = FlowFunctionPtrType; +}; + +class IDETypeStateAnalysisBase + : private IDETypeStateAnalysisBaseCommon, + private FlowFunctionTemplates< + IDETypeStateAnalysisBaseCommon::d_t, + IDETypeStateAnalysisBaseCommon::container_type> { +public: + virtual ~IDETypeStateAnalysisBase() = default; + +protected: + IDETypeStateAnalysisBase(LLVMAliasInfoRef PT) noexcept : PT(PT) {} + + using typename IDETypeStateAnalysisBaseCommon::container_type; + using typename IDETypeStateAnalysisBaseCommon::d_t; + using typename IDETypeStateAnalysisBaseCommon::f_t; + using typename IDETypeStateAnalysisBaseCommon::FlowFunctionPtrType; + using typename IDETypeStateAnalysisBaseCommon::n_t; + + // --- Flow Functions + + FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ); + FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun); + FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun, + n_t ExitStmt, n_t RetSite); + FlowFunctionPtrType getCallToRetFlowFunction(n_t CallSite, n_t RetSite, + llvm::ArrayRef Callees); + FlowFunctionPtrType getSummaryFlowFunction(n_t CallSite, f_t DestFun); + + // --- Utilities + + [[nodiscard]] virtual bool + isAPIFunction(llvm::StringRef Name) const noexcept = 0; + [[nodiscard]] virtual bool + isFactoryFunction(llvm::StringRef Name) const noexcept = 0; + [[nodiscard]] virtual bool + isTypeNameOfInterest(llvm::StringRef Name) const noexcept = 0; + + /** + * @brief Returns all alloca's that are (indirect) aliases of V. + * + * Currently PhASAR's points-to information does not include alloca + * instructions, since alloca instructions, i.e. memory locations, are of + * type T* for a target type T. Thus they do not alias directly. Therefore, + * for each alias of V we collect related alloca instructions by checking + * load and store instructions for used alloca's. + */ + container_type getRelevantAllocas(d_t V); + + /** + * @brief Returns whole-module aliases of V. + * + * This function retrieves whole-module points-to information. We store + * already computed points-to information in a cache to prevent expensive + * recomputation since the whole module points-to graph can be huge. This + * might become unnecessary once PhASAR's AliasGraph starts using a cache + * itself. + */ + container_type getWMAliasSet(d_t V); + + /** + * @brief Provides whole module aliases and relevant alloca's of V. + */ + container_type getWMAliasesAndAllocas(d_t V); + + /** + * @brief Provides local aliases and relevant alloca's of V. + */ + container_type getLocalAliasesAndAllocas(d_t V, llvm::StringRef Fname); + + /** + * @brief Checks if the type machtes the type of interest. + */ + bool hasMatchingType(d_t V); + +private: + FlowFunctionPtrType generateFromZero(d_t FactToGenerate) { + return generateFlow(FactToGenerate, LLVMZeroValue::getInstance()); + } + + bool hasMatchingTypeName(const llvm::Type *Ty); + + std::map AliasCache; + LLVMAliasInfoRef PT{}; + std::map> + RelevantAllocaCache; +}; +} // namespace detail + +template struct IDETypeStateAnalysisDomain : public LLVMAnalysisDomainDefault { - using l_t = int; + using l_t = typename TypeStateDescriptionTy::State; }; +template class IDETypeStateAnalysis - : public IDETabulationProblem { + : public IDETabulationProblem< + IDETypeStateAnalysisDomain>, + private detail::IDETypeStateAnalysisBase { public: - using IDETabProblemType = IDETabulationProblem; + using IDETabProblemType = + IDETabulationProblem>; + using typename IDETabProblemType::container_type; using typename IDETabProblemType::d_t; using typename IDETabProblemType::f_t; using typename IDETabProblemType::i_t; @@ -50,61 +160,317 @@ class IDETypeStateAnalysis using typename IDETabProblemType::t_t; using typename IDETabProblemType::v_t; - using ConfigurationTy = TypeStateDescription; + using typename IDETabProblemType::FlowFunctionPtrType; + using ConfigurationTy = TypeStateDescriptionTy; +private: + static AllBottom + makeAllBottom(const TypeStateDescriptionTy *TSD) noexcept { + if constexpr (HasJoinLatticeTraits) { + return AllBottom{}; + } else { + return AllBottom{TSD->bottom()}; + } + } + template >> + static AllBottom makeAllBottom(EmptyType /*unused*/) noexcept { + return AllBottom{}; + } + static bool isBottom(l_t State, const TypeStateDescriptionTy *TSD) noexcept { + if constexpr (HasJoinLatticeTraits) { + return State == JoinLatticeTraits::bottom(); + } else { + return State == TSD->bottom(); + } + } + template >> + static bool isBottom(l_t State, EmptyType /*unused*/) noexcept { + return State == JoinLatticeTraits::bottom(); + } + + struct TSEdgeFunctionComposer : EdgeFunctionComposer { + TSEdgeFunctionComposer(EdgeFunction First, EdgeFunction Second, + const TypeStateDescriptionTy *TSD) noexcept + : EdgeFunctionComposer{std::move(First), std::move(Second)} { + if constexpr (!HasJoinLatticeTraits) { + BotElement = TSD->bottom(); + } + } + + [[no_unique_address]] std::conditional_t, + EmptyType, l_t> + BotElement{}; + + static EdgeFunction join(EdgeFunctionRef This, + const EdgeFunction &OtherFunction) { + if (auto Default = defaultJoinOrNull(This, OtherFunction)) { + return Default; + } + if constexpr (HasJoinLatticeTraits) { + return AllBottom{}; + } else { + return AllBottom{This->BotElement}; + } + } + }; + + struct TSEdgeFunction { + using l_t = l_t; + const TypeStateDescriptionTy *TSD{}; + // XXX: Do we really need a string here? Can't we just use an integer or sth + // else that is cheap? + std::string Token; + const llvm::CallBase *CallSite{}; + + [[nodiscard]] l_t computeTarget(l_t Source) const { + + // assert((Source != TSD->top()) && "Error: call computeTarget with + // TOP\n"); + + auto CurrentState = TSD->getNextState( + Token, Source == TSD->top() ? TSD->uninit() : Source, CallSite); + PHASAR_LOG_LEVEL(DEBUG, "State machine transition: (" + << Token << " , " << LToString(Source) + << ") -> " << LToString(CurrentState)); + return CurrentState; + } + + static EdgeFunction compose(EdgeFunctionRef This, + const EdgeFunction &SecondFunction) { + if (auto Default = defaultComposeOrNull(This, SecondFunction)) { + return Default; + } + + return TSEdgeFunctionComposer{This, SecondFunction, This->TSD}; + } + + static EdgeFunction join(EdgeFunctionRef This, + const EdgeFunction &OtherFunction) { + if (auto Default = defaultJoinOrNull(This, OtherFunction)) { + return Default; + } + + return makeAllBottom(This->TSD); + } + + bool operator==(const TSEdgeFunction &Other) const { + return CallSite == Other.CallSite && Token == Other.Token; + } + + friend llvm::raw_ostream &print(llvm::raw_ostream &OS, + const TSEdgeFunction &TSE) { + return OS << "TSEF(" << TSE.Token << " at " + << llvmIRToShortString(TSE.CallSite) << ")"; + } + }; + + struct TSConstant : ConstantEdgeFunction { + std::conditional_t, EmptyType, + const TypeStateDescriptionTy *> + TSD{}; + + TSConstant(l_t Value, const TypeStateDescriptionTy *TSD) noexcept + : ConstantEdgeFunction{Value} { + if constexpr (!HasJoinLatticeTraits) { + this->TSD = TSD; + } + } + + template >> + TSConstant(l_t Value, EmptyType /*unused*/ = {}) noexcept + : ConstantEdgeFunction{Value} { + if constexpr (!HasJoinLatticeTraits) { + this->TSD = TSD; + } + } + + /// XXX: Cannot default compose() and join(), because l_t does not implement + /// JoinLatticeTraits (because bottom value is not constant) + template + static EdgeFunction compose(EdgeFunctionRef This, + const EdgeFunction &SecondFunction) { + + if (auto Default = defaultComposeOrNull(This, SecondFunction)) { + return Default; + } + + l_t Ret = SecondFunction.computeTarget(This->Value); + if (Ret == This->Value) { + return This; + } + if (isBottom(Ret, This->TSD)) { + return makeAllBottom(This->TSD); + } + + return TSConstant{Ret, This->TSD}; + } + + template + static EdgeFunction join(EdgeFunctionRef This, + const EdgeFunction &OtherFunction) { + if (auto Default = defaultJoinOrNull(This, OtherFunction)) { + return Default; + } + + auto Top = [TSD = This->TSD] { + if constexpr (HasJoinLatticeTraits) { + return JoinLatticeTraits::top(); + } else { + return TSD->top(); + } + }(); + if (const auto *C = llvm::dyn_cast(OtherFunction)) { + if (C->Value == This->Value || C->Value == Top) { + return This; + } + if (This->Value == Top) { + return OtherFunction; + } + } + return makeAllBottom(This->TSD); + } + + bool operator==(const TSConstant &Other) const noexcept { + return this->Value == Other.Value; + } + + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const TSConstant &EF) { + return OS << "TSConstant[" << LToString(EF.Value) << "]"; + } + }; + +public: IDETypeStateAnalysis(const LLVMProjectIRDB *IRDB, LLVMAliasInfoRef PT, - const TypeStateDescription *TSD, - std::vector EntryPoints = {"main"}); + const TypeStateDescriptionTy *TSD, + std::vector EntryPoints = {"main"}) + : IDETabProblemType(IRDB, std::move(EntryPoints), createZeroValue()), + IDETypeStateAnalysisBase(PT), TSD(TSD) { + assert(TSD != nullptr); + assert(PT); + } ~IDETypeStateAnalysis() override = default; // start formulating our analysis by specifying the parts required for IFDS - FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override; + FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override { + return detail::IDETypeStateAnalysisBase::getNormalFlowFunction(Curr, Succ); + } - FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) override; + FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) override { + return detail::IDETypeStateAnalysisBase::getCallFlowFunction(CallSite, + DestFun); + } FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun, - n_t ExitStmt, n_t RetSite) override; + n_t ExitStmt, n_t RetSite) override { + + return detail::IDETypeStateAnalysisBase::getRetFlowFunction( + CallSite, CalleeFun, ExitStmt, RetSite); + } FlowFunctionPtrType getCallToRetFlowFunction(n_t CallSite, n_t RetSite, - llvm::ArrayRef Callees) override; + llvm::ArrayRef Callees) override { + return detail::IDETypeStateAnalysisBase::getCallToRetFlowFunction( + CallSite, RetSite, Callees); + } FlowFunctionPtrType getSummaryFlowFunction(n_t CallSite, - f_t DestFun) override; + f_t DestFun) override { + return detail::IDETypeStateAnalysisBase::getSummaryFlowFunction(CallSite, + DestFun); + } - InitialSeeds initialSeeds() override; + InitialSeeds initialSeeds() override { + return this->createDefaultSeeds(); + } - [[nodiscard]] d_t createZeroValue() const; + [[nodiscard]] d_t createZeroValue() const { + return LLVMZeroValue::getInstance(); + } - [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; + [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override { + return LLVMZeroValue::isLLVMZeroValue(Fact); + } // in addition provide specifications for the IDE parts - EdgeFunction getNormalEdgeFunction(n_t Curr, d_t CurrNode, n_t Succ, - d_t SuccNode) override; - - EdgeFunction getCallEdgeFunction(n_t CallSite, d_t SrcNode, - f_t DestinationFunction, - d_t DestNode) override; - - EdgeFunction getReturnEdgeFunction(n_t CallSite, f_t CalleeFunction, - n_t ExitInst, d_t ExitNode, - n_t RetSite, d_t RetNode) override; + EdgeFunction getNormalEdgeFunction(n_t Curr, d_t CurrNode, n_t /*Succ*/, + d_t SuccNode) override { + // Set alloca instructions of target type to uninitialized. + if (const auto *Alloca = llvm::dyn_cast(Curr)) { + if (hasMatchingType(Alloca)) { + if (LLVMZeroValue::isLLVMZeroValue(CurrNode) && SuccNode == Alloca) { + return TSConstant(TSD->uninit(), TSD); + } + } + } + return EdgeIdentity{}; + } + + EdgeFunction getCallEdgeFunction(n_t /*CallSite*/, d_t /*SrcNode*/, + f_t /*DestinationFunction*/, + d_t /*DestNode*/) override { + return EdgeIdentity{}; + } + + EdgeFunction getReturnEdgeFunction(n_t /*CallSite*/, + f_t /*CalleeFunction*/, + n_t /*ExitInst*/, d_t /*ExitNode*/, + n_t /*RetSite*/, + d_t /*RetNode*/) override { + return EdgeIdentity{}; + } EdgeFunction - getCallToRetEdgeFunction(n_t CallSite, d_t CallNode, n_t RetSite, + getCallToRetEdgeFunction(n_t CallSite, d_t CallNode, n_t /*RetSite*/, d_t RetSiteNode, - llvm::ArrayRef Callees) override; - - EdgeFunction getSummaryEdgeFunction(n_t CallSite, d_t CallNode, - n_t RetSite, - d_t RetSiteNode) override; - - l_t topElement() override; - - l_t bottomElement() override; + llvm::ArrayRef Callees) override { + const auto *CS = llvm::cast(CallSite); + for (const auto *Callee : Callees) { + std::string DemangledFname = llvm::demangle(Callee->getName().str()); + + // For now we assume that we can only generate from the return value. + // We apply the same edge function for the return value, i.e. callsite. + if (TSD->isFactoryFunction(DemangledFname)) { + PHASAR_LOG_LEVEL(DEBUG, "Processing factory function"); + if (isZeroValue(CallNode) && RetSiteNode == CS) { + return TSConstant{ + TSD->getNextState(DemangledFname, TSD->uninit(), CS), TSD}; + } + } + + // For every consuming parameter and all its aliases and relevant alloca's + // we apply the same edge function. + if (TSD->isConsumingFunction(DemangledFname)) { + PHASAR_LOG_LEVEL(DEBUG, "Processing consuming function"); + for (auto Idx : TSD->getConsumerParamIdx(DemangledFname)) { + const auto &AliasAndAllocas = + getWMAliasesAndAllocas(CS->getArgOperand(Idx)); + + if (CallNode == RetSiteNode && AliasAndAllocas.count(CallNode)) { + return TSEdgeFunction{TSD, DemangledFname, CS}; + } + } + } + } + return EdgeIdentity{}; + } + + EdgeFunction getSummaryEdgeFunction(n_t /*CallSite*/, d_t /*CallNode*/, + n_t /*RetSite*/, + d_t /*RetSiteNode*/) override { + return nullptr; + } + + l_t topElement() override { return TSD->top(); } + + l_t bottomElement() override { return TSD->bottom(); } /** * We have a lattice with BOTTOM representing all information @@ -114,65 +480,124 @@ class IDETypeStateAnalysis * * @note Only one-level lattice's are handled currently */ - l_t join(l_t Lhs, l_t Rhs) override; - - EdgeFunction allTopFunction() override; - - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - - void printEdgeFact(llvm::raw_ostream &OS, l_t L) const override; + l_t join(l_t Lhs, l_t Rhs) override { + if (Lhs == Rhs) { + return Lhs; + } + if (Lhs == TSD->top()) { + return Rhs; + } + if (Rhs == TSD->top()) { + return Lhs; + } + return TSD->bottom(); + } + + EdgeFunction allTopFunction() override { + if constexpr (HasJoinLatticeTraits) { + return AllTop{}; + } else { + return AllTop{topElement()}; + } + } + + [[nodiscard]] bool + isAPIFunction(llvm::StringRef Name) const noexcept override { + return TSD->isAPIFunction(Name); + } + + [[nodiscard]] bool + isFactoryFunction(llvm::StringRef Name) const noexcept override { + return TSD->isFactoryFunction(Name); + } + + [[nodiscard]] bool + isTypeNameOfInterest(llvm::StringRef Name) const noexcept override { + return Name.contains(TSD->getTypeNameOfInterest()); + } void emitTextReport(const SolverResults &SR, - llvm::raw_ostream &OS = llvm::outs()) override; + 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'; + } + } else { + OS << "\nInst: " << NToString(&I) << '\n' + << "Fact: " << DToString(Res.first) << '\n' + << "State: " << LToString(Res.second) << '\n'; + } + } + } else { + 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' + << "\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"; + } + } else { + OS << "\nInst: " << NToString(&I) << '\n' + << "Fact: " << DToString(Res.first) << '\n' + << "State: " << LToString(Res.second) << '\n'; + } + } + } + } + } + OS << "\n--------------------------------------------\n"; + } + } private: - const TypeStateDescription *TSD{}; - std::map AliasCache; - LLVMAliasInfoRef PT{}; - std::map> - RelevantAllocaCache; - - /** - * @brief Returns all alloca's that are (indirect) aliases of V. - * - * Currently PhASAR's points-to information does not include alloca - * instructions, since alloca instructions, i.e. memory locations, are of - * type T* for a target type T. Thus they do not alias directly. Therefore, - * for each alias of V we collect related alloca instructions by checking - * load and store instructions for used alloca's. - */ - std::set getRelevantAllocas(d_t V); - - /** - * @brief Returns whole-module aliases of V. - * - * This function retrieves whole-module points-to information. We store - * already computed points-to information in a cache to prevent expensive - * recomputation since the whole module points-to graph can be huge. This - * might become unnecessary once PhASAR's AliasGraph starts using a cache - * itself. - */ - std::set getWMAliasSet(d_t V); + const TypeStateDescriptionTy *TSD{}; +}; - /** - * @brief Provides whole module aliases and relevant alloca's of V. - */ - std::set getWMAliasesAndAllocas(d_t V); +template +IDETypeStateAnalysis(const LLVMProjectIRDB *, LLVMAliasInfoRef, + const TypeStateDescriptionTy *, + std::vector EntryPoints) + -> IDETypeStateAnalysis; - /** - * @brief Provides local aliases and relevant alloca's of V. - */ - std::set getLocalAliasesAndAllocas(d_t V, const std::string &Fname); +// class CSTDFILEIOTypeStateDescription; - /** - * @brief Checks if the type machtes the type of interest. - */ - bool hasMatchingType(d_t V); -}; +// extern template class IDETypeStateAnalysis; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h index ca503b29fa..590513a444 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.h @@ -144,12 +144,6 @@ class IFDSConstAnalysis [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - void emitTextReport(const SolverResults &SR, llvm::raw_ostream &OS = llvm::outs()) override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h index 853c04404c..135a518113 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.h @@ -85,41 +85,14 @@ class IFDSFieldSensTaintAnalysis return LLVMZeroValue::isLLVMZeroValue(EV.getValue()); } - void printNode(llvm::raw_ostream &OS, - const llvm::Instruction *Stmt) const override { - OS << llvmIRToString(Stmt); - } - - void printDataFlowFact(llvm::raw_ostream &OS, - ExtendedValue EV) const override { - OS << llvmIRToString(EV.getValue()) << "\n"; - for (const auto *MemLocationPart : EV.getMemLocationSeq()) { - OS << "A:\t" << llvmIRToString(MemLocationPart) << "\n"; - } - if (!EV.getEndOfTaintedBlockLabel().empty()) { - OS << "L:\t" << EV.getEndOfTaintedBlockLabel() << "\n"; - } - if (EV.isVarArg()) { - OS << "VT:\t" << EV.isVarArgTemplate() << "\n"; - for (const auto *VAListMemLocationPart : EV.getVaListMemLocationSeq()) { - OS << "VLA:\t" << llvmIRToString(VAListMemLocationPart) << "\n"; - } - OS << "VI:\t" << EV.getVarArgIndex() << "\n"; - OS << "CI:\t" << EV.getCurrentVarArgIndex() << "\n"; - } - } - - void printFunction(llvm::raw_ostream &OS, - const llvm::Function *Func) const override { - OS << Func->getName(); - } - private: const LLVMTaintConfig *Config{}; TraceStats Stats{}; }; +std::string DToString(const ExtendedValue &EV); + } // namespace psr #endif diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h index 8cf494155a..fb1db483c9 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.h @@ -53,12 +53,6 @@ class IFDSProtoAnalysis [[nodiscard]] d_t createZeroValue() const; [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; - - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h index a2e2ff1201..54338de635 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.h @@ -54,12 +54,6 @@ class IFDSSignAnalysis [[nodiscard]] d_t createZeroValue() const; [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; - - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h index 178e8f0920..edf176f775 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.h @@ -52,12 +52,6 @@ class IFDSSolverTest [[nodiscard]] d_t createZeroValue() const; [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; - - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h index f02ebfb810..5e6d85ccf3 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h @@ -79,12 +79,6 @@ class IFDSTaintAnalysis bool isZeroValue(d_t FlowFact) const noexcept override; - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t FlowFact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override; - void emitTextReport(const SolverResults &SR, llvm::raw_ostream &OS = llvm::outs()) override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h index 1527bf3503..8f5c8c04fb 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.h @@ -45,12 +45,6 @@ class IFDSTypeAnalysis [[nodiscard]] d_t createZeroValue() const; [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; - - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h index 597902ae6f..c6a92f457a 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h @@ -62,12 +62,6 @@ class IFDSUninitializedVariables [[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; - void printNode(llvm::raw_ostream &OS, n_t Stmt) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Func) const override; - void emitTextReport(const SolverResults &Results, llvm::raw_ostream &OS = llvm::outs()) override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h index ef36022a70..1f28206d17 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_TYPESTATEDESCRIPTIONS_CSTDFILEIOTYPESTATEDESCRIPTION_H #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_TYPESTATEDESCRIPTIONS_CSTDFILEIOTYPESTATEDESCRIPTION_H +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h" #include @@ -18,55 +19,54 @@ namespace psr { +enum class CSTDFILEIOState { + TOP = 42, + UNINIT = 0, + OPENED = 1, + CLOSED = 2, + ERROR = 3, + BOT = 4 +}; +llvm::StringRef to_string(CSTDFILEIOState State) noexcept; +template <> struct JoinLatticeTraits { + static constexpr CSTDFILEIOState top() noexcept { + return CSTDFILEIOState::TOP; + } + static constexpr CSTDFILEIOState bottom() noexcept { + return CSTDFILEIOState::BOT; + } + static constexpr CSTDFILEIOState join(CSTDFILEIOState L, + CSTDFILEIOState R) noexcept { + if (L == top() || R == bottom()) { + return R; + } + if (L == bottom() || R == top()) { + return L; + } + return bottom(); + } +}; + /** * A type state description for C's file I/O API. The finite state machine * is encoded by a two-dimensional array with rows as function tokens and * columns as states. */ -class CSTDFILEIOTypeStateDescription : public TypeStateDescription { -private: - /** - * We use the following lattice - * BOT = all information - * - * UNINIT OPENED CLOSED ERROR - * - * TOP = no information - */ - enum CSTDFILEIOState { - TOP = 42, - UNINIT = 0, - OPENED = 1, - CLOSED = 2, - ERROR = 3, - BOT = 4 - }; - - /** - * The STAR token represents all API functions besides fopen(), fdopen() and - * fclose(). FOPEN covers fopen() and fdopen() since both functions are - * modeled the same in our case. - */ - enum class CSTDFILEIOToken { FOPEN = 0, FCLOSE = 1, STAR = 2 }; - - static const std::map> StdFileIOFuncs; - // delta matrix to implement the state machine's delta function - static const CSTDFILEIOState Delta[3][5]; - static CSTDFILEIOToken funcNameToToken(const std::string &F); - +class CSTDFILEIOTypeStateDescription + : public TypeStateDescription { public: - [[nodiscard]] bool isFactoryFunction(const std::string &F) const override; - [[nodiscard]] bool isConsumingFunction(const std::string &F) const override; - [[nodiscard]] bool isAPIFunction(const std::string &F) const override; + using TypeStateDescription::getNextState; + [[nodiscard]] bool isFactoryFunction(llvm::StringRef F) const override; + [[nodiscard]] bool isConsumingFunction(llvm::StringRef F) const override; + [[nodiscard]] bool isAPIFunction(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State - getNextState(std::string Tok, TypeStateDescription::State S) const override; + getNextState(llvm::StringRef Tok, + TypeStateDescription::State S) const override; [[nodiscard]] std::string getTypeNameOfInterest() const override; [[nodiscard]] std::set - getConsumerParamIdx(const std::string &F) const override; + getConsumerParamIdx(llvm::StringRef F) const override; [[nodiscard]] std::set - getFactoryParamIdx(const std::string &F) const override; - [[nodiscard]] std::string - stateToString(TypeStateDescription::State S) const override; + getFactoryParamIdx(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State bottom() const override; [[nodiscard]] TypeStateDescription::State top() const override; [[nodiscard]] TypeStateDescription::State uninit() const override; @@ -74,6 +74,8 @@ class CSTDFILEIOTypeStateDescription : public TypeStateDescription { [[nodiscard]] TypeStateDescription::State error() const override; }; +extern template class IDETypeStateAnalysis; + } // namespace psr #endif diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h index 0a31b6042b..081b94a46a 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h @@ -13,9 +13,8 @@ #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" #include "phasar/Domain/AnalysisDomain.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h" -#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h" -#include #include #include #include @@ -27,32 +26,35 @@ class Value; namespace psr { +/** + * We use the following lattice + * BOT = all information + * + * UNINIT CTX_ATTACHED PARAM_INIT DERIVED ERROR + * + * TOP = no information + */ +enum class OpenSSLEVPKDFCTXState { + TOP = 42, + UNINIT = 5, + CTX_ATTACHED = 1, + PARAM_INIT = 2, + DERIVED = 3, + ERROR = 4, + BOT = 0 // It is VERY IMPORTANT, athat BOT has value 0, since this is the + // default value +}; + +llvm::StringRef to_string(OpenSSLEVPKDFCTXState State) noexcept; + /** * A type state description for OpenSSL's EVP Key Derivation functions. The * finite state machine is encoded by a two-dimensional array with rows as * function tokens and columns as states. */ -class OpenSSLEVPKDFCTXDescription : public TypeStateDescription { +class OpenSSLEVPKDFCTXDescription + : public TypeStateDescription { private: - /** - * We use the following lattice - * BOT = all information - * - * UNINIT CTX_ATTACHED PARAM_INIT DERIVED ERROR - * - * TOP = no information - */ - enum OpenSSLEVPKDFState { - TOP = 42, - UNINIT = 5, - CTX_ATTACHED = 1, - PARAM_INIT = 2, - DERIVED = 3, - ERROR = 4, - BOT = 0 // It is VERY IMPORTANT, athat BOT has value 0, since this is the - // default value - }; - /** * The STAR token represents all functions besides EVP_KDF_fetch(), * EVP_KDF_CTX_new(), EVP_KDF_CTX_set_params() ,derive() and @@ -66,42 +68,40 @@ class OpenSSLEVPKDFCTXDescription : public TypeStateDescription { STAR = 4 }; - static const std::map> OpenSSLEVPKDFFuncs; // Delta matrix to implement the state machine's Delta function - static const OpenSSLEVPKDFState Delta[5][6]; + static const OpenSSLEVPKDFCTXState Delta[5][6]; // std::map, int> // requiredKDFState; - IDESolver &KDFAnalysisResults; - static OpenSSLEVTKDFToken funcNameToToken(const std::string &F); + IDESolver> + &KDFAnalysisResults; + static OpenSSLEVTKDFToken funcNameToToken(llvm::StringRef F); public: + using TypeStateDescription::getNextState; OpenSSLEVPKDFCTXDescription( - IDESolver &KDFAnalysisResults) + IDESolver> + &KDFAnalysisResults) : KDFAnalysisResults(KDFAnalysisResults) {} + [[nodiscard]] bool isFactoryFunction(llvm::StringRef FuncName) const override; [[nodiscard]] bool - isFactoryFunction(const std::string &FuncName) const override; - [[nodiscard]] bool - isConsumingFunction(const std::string &FuncName) const override; - [[nodiscard]] bool isAPIFunction(const std::string &FuncName) const override; - [[nodiscard]] TypeStateDescription::State - getNextState(std::string Tok, TypeStateDescription::State S) const override; - [[nodiscard]] TypeStateDescription::State - getNextState(const std::string &Tok, TypeStateDescription::State S, + isConsumingFunction(llvm::StringRef FuncName) const override; + [[nodiscard]] bool isAPIFunction(llvm::StringRef FuncName) const override; + [[nodiscard]] State getNextState(llvm::StringRef Tok, State S) const override; + [[nodiscard]] State + getNextState(llvm::StringRef Tok, State S, const llvm::CallBase *CallSite) const override; [[nodiscard]] std::string getTypeNameOfInterest() const override; [[nodiscard]] std::set - getConsumerParamIdx(const std::string &F) const override; + getConsumerParamIdx(llvm::StringRef F) const override; [[nodiscard]] std::set - getFactoryParamIdx(const std::string &F) const override; - [[nodiscard]] std::string - stateToString(TypeStateDescription::State S) const override; - [[nodiscard]] TypeStateDescription::State bottom() const override; - [[nodiscard]] TypeStateDescription::State top() const override; - [[nodiscard]] TypeStateDescription::State uninit() const override; - [[nodiscard]] TypeStateDescription::State start() const override; - [[nodiscard]] TypeStateDescription::State error() const override; + getFactoryParamIdx(llvm::StringRef F) const override; + [[nodiscard]] State bottom() const override; + [[nodiscard]] State top() const override; + [[nodiscard]] State uninit() const override; + [[nodiscard]] State start() const override; + [[nodiscard]] State error() 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 f038e04a68..34023c863a 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h @@ -17,24 +17,28 @@ #include namespace psr { -class OpenSSLEVPKDFDescription : public TypeStateDescription { -public: - /** - * We use the following lattice - * BOT = all information - * - * UNINIT KDF_FETCHED ERROR - * - * TOP = no information - */ - enum OpenSSLEVPKDFState { - TOP = 42, - UNINIT = 0, - KDF_FETCHED = 1, - ERROR = 2, - BOT = 3 - }; +/** + * We use the following lattice + * BOT = all information + * + * UNINIT KDF_FETCHED ERROR + * + * TOP = no information + */ +enum class OpenSSLEVPKDFState { + TOP = 42, + UNINIT = 0, + KDF_FETCHED = 1, + ERROR = 2, + BOT = 3 +}; + +llvm::StringRef to_string(OpenSSLEVPKDFState State) noexcept; + +class OpenSSLEVPKDFDescription + : public TypeStateDescription { +public: /** * The STAR token represents all functions besides EVP_KDF_fetch(), * EVP_KDF_fetch() and EVP_KDF_CTX_free(). @@ -45,32 +49,32 @@ class OpenSSLEVPKDFDescription : public TypeStateDescription { STAR = 2 }; + using State = OpenSSLEVPKDFState; + private: - static const std::map> OpenSSLEVPKDFFuncs; // delta matrix to implement the state machine's delta function static const OpenSSLEVPKDFState Delta[3][4]; - static OpenSSLEVTKDFToken funcNameToToken(const std::string &F); + static OpenSSLEVTKDFToken funcNameToToken(llvm::StringRef F); public: - [[nodiscard]] bool isFactoryFunction(const std::string &F) const override; + using TypeStateDescription::getNextState; + [[nodiscard]] bool isFactoryFunction(llvm::StringRef F) const override; - [[nodiscard]] bool isConsumingFunction(const std::string &F) const override; + [[nodiscard]] bool isConsumingFunction(llvm::StringRef F) const override; - [[nodiscard]] bool isAPIFunction(const std::string &F) const override; + [[nodiscard]] bool isAPIFunction(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State - getNextState(std::string Tok, TypeStateDescription::State S) const override; + getNextState(llvm::StringRef Tok, + TypeStateDescription::State S) const override; [[nodiscard]] std::string getTypeNameOfInterest() const override; [[nodiscard]] std::set - getConsumerParamIdx(const std::string &F) const override; + getConsumerParamIdx(llvm::StringRef F) const override; [[nodiscard]] std::set - getFactoryParamIdx(const std::string &F) const override; - - [[nodiscard]] std::string - stateToString(TypeStateDescription::State S) const override; + getFactoryParamIdx(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State bottom() const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h index f0b0c6ab99..cb69f4fe7e 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h @@ -15,24 +15,23 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h" -#include -#include #include namespace psr { +enum class OpenSSLSecureHeapState { + TOP = 42, + BOT = 0, + UNINIT = 1, + ALLOCATED = 2, + ZEROED = 3, + FREED = 4, + ERROR = 5 +}; +llvm::StringRef to_string(OpenSSLSecureHeapState State) noexcept; -class OpenSSLSecureHeapDescription : public TypeStateDescription { +class OpenSSLSecureHeapDescription + : public TypeStateDescription { private: - enum OpenSSLSecureHeapState { - TOP = 42, - BOT = 0, - UNINIT = 1, - ALLOCATED = 2, - ZEROED = 3, - FREED = 4, - ERROR = 5 - }; - enum class OpenSSLSecureHeapToken { SECURE_MALLOC = 0, SECURE_ZALLOC = 1, @@ -41,34 +40,33 @@ class OpenSSLSecureHeapDescription : public TypeStateDescription { STAR = 4 }; - static const std::map> OpenSSLSecureHeapFuncs; // Delta matrix to implement the state machine's Delta function static const OpenSSLSecureHeapState Delta[5][6]; IDESolver &SecureHeapPropagationResults; - static OpenSSLSecureHeapToken funcNameToToken(const std::string &F); + static OpenSSLSecureHeapToken funcNameToToken(llvm::StringRef F); public: + using TypeStateDescription::getNextState; OpenSSLSecureHeapDescription(IDESolver &SecureHeapPropagationResults); - [[nodiscard]] bool isFactoryFunction(const std::string &F) const override; - [[nodiscard]] bool isConsumingFunction(const std::string &F) const override; - [[nodiscard]] bool isAPIFunction(const std::string &F) const override; + [[nodiscard]] bool isFactoryFunction(llvm::StringRef F) const override; + [[nodiscard]] bool isConsumingFunction(llvm::StringRef F) const override; + [[nodiscard]] bool isAPIFunction(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State - getNextState(std::string Tok, TypeStateDescription::State S) const override; + getNextState(llvm::StringRef Tok, + TypeStateDescription::State S) const override; [[nodiscard]] TypeStateDescription::State - getNextState(const std::string &Tok, TypeStateDescription::State S, + getNextState(llvm::StringRef Tok, TypeStateDescription::State S, const llvm::CallBase *CallSite) const override; [[nodiscard]] std::string getTypeNameOfInterest() const override; [[nodiscard]] std::set - getConsumerParamIdx(const std::string &F) const override; + getConsumerParamIdx(llvm::StringRef F) const override; [[nodiscard]] std::set - getFactoryParamIdx(const std::string &F) const override; - [[nodiscard]] std::string - stateToString(TypeStateDescription::State S) const override; + getFactoryParamIdx(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State bottom() const override; [[nodiscard]] TypeStateDescription::State top() const override; [[nodiscard]] TypeStateDescription::State uninit() const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h index 5f06867f2d..a1c41d1c27 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h @@ -18,43 +18,24 @@ namespace psr { -class OpenSSLSecureMemoryDescription : public TypeStateDescription { -private: - enum OpenSSLSecureMemoryState { - TOP = 42, - BOT = 0, - ZEROED = 1, - FREED = 2, - ERROR = 3, - ALLOCATED = 4 - }; - - enum class OpenSSLSecureMemoryToken { - CRYPTO_MALLOC = 0, - CRYPTO_ZALLOC = 1, - CRYPTO_FREE = 2, - OPENSSL_CLEANSE = 3, - STAR = 4 - }; - - static const std::map> OpenSSLSecureMemoryFuncs; - // Delta matrix to implement the state machine's Delta function - static const OpenSSLSecureMemoryState Delta[6][7]; - static OpenSSLSecureMemoryToken funcNameToToken(const std::string &F); +enum class OpenSSLSecureMemoryState; +llvm::StringRef to_string(OpenSSLSecureMemoryState State) noexcept; +class OpenSSLSecureMemoryDescription + : public TypeStateDescription { public: - [[nodiscard]] bool isFactoryFunction(const std::string &F) const override; - [[nodiscard]] bool isConsumingFunction(const std::string &F) const override; - [[nodiscard]] bool isAPIFunction(const std::string &F) const override; + using TypeStateDescription::getNextState; + [[nodiscard]] bool isFactoryFunction(llvm::StringRef F) const override; + [[nodiscard]] bool isConsumingFunction(llvm::StringRef F) const override; + [[nodiscard]] bool isAPIFunction(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State - getNextState(std::string Tok, TypeStateDescription::State S) const override; + getNextState(llvm::StringRef Tok, + TypeStateDescription::State S) const override; [[nodiscard]] std::string getTypeNameOfInterest() const override; [[nodiscard]] std::set - getConsumerParamIdx(const std::string &F) const override; + getConsumerParamIdx(llvm::StringRef F) const override; [[nodiscard]] std::set - getFactoryParamIdx(const std::string &F) const override; - [[nodiscard]] std::string - stateToString(TypeStateDescription::State S) const override; + getFactoryParamIdx(llvm::StringRef F) const override; [[nodiscard]] TypeStateDescription::State bottom() const override; [[nodiscard]] TypeStateDescription::State top() const override; [[nodiscard]] TypeStateDescription::State uninit() const override; diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h index a67b119ba6..883b1d89d6 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h @@ -17,6 +17,19 @@ namespace psr { +struct TypeStateDescriptionBase { + virtual ~TypeStateDescriptionBase() = default; + + [[nodiscard]] virtual bool isFactoryFunction(llvm::StringRef F) const = 0; + [[nodiscard]] virtual bool isConsumingFunction(llvm::StringRef F) const = 0; + [[nodiscard]] virtual bool isAPIFunction(llvm::StringRef F) const = 0; + [[nodiscard]] virtual std::string getTypeNameOfInterest() const = 0; + [[nodiscard]] virtual std::set + getConsumerParamIdx(llvm::StringRef F) const = 0; + [[nodiscard]] virtual std::set + getFactoryParamIdx(llvm::StringRef F) const = 0; +}; + /** * Interface for a type state problem to be used with the IDETypeStateAnalysis. * It needs to provide a finite state machine to handle state changes and a list @@ -31,31 +44,24 @@ namespace psr { * * @see CSTDFILEIOTypeStateDescription as an example of type state description. */ -struct TypeStateDescription { +template +struct TypeStateDescription : public TypeStateDescriptionBase { /// Type for states of the finite state machine - using State = int; - virtual ~TypeStateDescription() = default; - [[nodiscard]] virtual bool isFactoryFunction(const std::string &F) const = 0; - [[nodiscard]] virtual bool - isConsumingFunction(const std::string &F) const = 0; - [[nodiscard]] virtual bool isAPIFunction(const std::string &F) const = 0; + using State = StateTy; + ~TypeStateDescription() override = default; /** * @brief For a given function name (as a string token) and a state, this * function returns the next state. */ - [[nodiscard]] virtual State getNextState(std::string Tok, State S) const = 0; + [[nodiscard]] virtual State getNextState(llvm::StringRef Tok, + State S) const = 0; [[nodiscard]] virtual State - getNextState(const std::string &Tok, State S, + getNextState(llvm::StringRef Tok, State S, const llvm::CallBase * /*CallSite*/) const { return getNextState(Tok, S); } - [[nodiscard]] virtual std::string getTypeNameOfInterest() const = 0; - [[nodiscard]] virtual std::set - getConsumerParamIdx(const std::string &F) const = 0; - [[nodiscard]] virtual std::set - getFactoryParamIdx(const std::string &F) const = 0; - [[nodiscard]] virtual std::string stateToString(State S) const = 0; + [[nodiscard]] virtual State bottom() const = 0; [[nodiscard]] virtual State top() const = 0; diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h index 4c6e0e798b..df91bce7d7 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h @@ -75,12 +75,6 @@ class InterMonoFullConstantPropagation std::unordered_map initialSeeds() override; - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override; - void printContainer(llvm::raw_ostream &OS, mono_container_t Con) const override; }; diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h index 235d9a31e2..8674ff564d 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h @@ -77,12 +77,6 @@ class InterMonoSolverTest : public InterMonoProblem { const mono_container_t &In) override; std::unordered_map initialSeeds() override; - - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h index c155f1b71e..211de3a916 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h @@ -82,12 +82,6 @@ class InterMonoTaintAnalysis std::unordered_map initialSeeds() override; - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override; - [[nodiscard]] const std::map> &getAllLeaks() const; private: diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h index e62d243690..010e2f517d 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h @@ -22,6 +22,7 @@ #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/Utils/BitVectorSet.h" +#include "phasar/Utils/Printer.h" #include #include @@ -44,10 +45,15 @@ class LLVMBasedICFG; class LLVMTypeHierarchy; class InterMonoFullConstantPropagation; +struct IntraMonoFCAFact { + const llvm::Value *Fact{}; + LatticeDomain Value{}; +}; + struct IntraMonoFullConstantPropagationAnalysisDomain : public LLVMAnalysisDomainDefault { using plain_d_t = int64_t; - using d_t = std::pair>; + using d_t = IntraMonoFCAFact; using mono_container_t = std::map>; }; @@ -90,31 +96,23 @@ class IntraMonoFullConstantPropagation const mono_container_t &Rhs) override; std::unordered_map initialSeeds() override; - - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override; }; +std::string DToString(const IntraMonoFCAFact &Fact); + } // namespace psr namespace std { -template <> -struct hash>> { - size_t operator()(const std::pair> &P) const { +template <> struct hash { + size_t operator()(const psr::IntraMonoFCAFact &P) const { std::hash HashPtr; - size_t HP = HashPtr(P.first); + size_t HP = HashPtr(P.Fact); size_t HU = 0; // returns nullptr if P.second is Top or Bottom, a valid pointer otherwise if (const auto *Ptr = std::get_if( - &P.second)) { + &P.Value)) { HU = *Ptr; } return HP ^ (HU << 1); diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h index 05a95b2931..13c5ac42f3 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h @@ -69,13 +69,6 @@ class IntraMonoSolverTest mono_container_t normalFlow(n_t Inst, const mono_container_t &In) override; std::unordered_map initialSeeds() override; - - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, - const llvm::Function *Fun) const override; }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h index 7b1f887b87..e813e38d33 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h @@ -65,12 +65,6 @@ class IntraMonoUninitVariables mono_container_t normalFlow(n_t Inst, const mono_container_t &In) override; std::unordered_map initialSeeds() override; - - void printNode(llvm::raw_ostream &OS, n_t Inst) const override; - - void printDataFlowFact(llvm::raw_ostream &OS, d_t Fact) const override; - - void printFunction(llvm::raw_ostream &OS, f_t Fun) const override; }; } // namespace psr diff --git a/include/phasar/Utils/Printer.h b/include/phasar/Utils/Printer.h index c8f70578db..31a08cdb4a 100644 --- a/include/phasar/Utils/Printer.h +++ b/include/phasar/Utils/Printer.h @@ -10,106 +10,109 @@ #ifndef PHASAR_UTILS_PRINTER_H #define PHASAR_UTILS_PRINTER_H +#include "phasar/Utils/TypeTraits.h" + +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include #include +#include -namespace psr { - -template -std::string toStringBuilder(void (P::*Printer)(llvm::raw_ostream &, T) const, - const P *This, const T &Arg) { - std::string Buffer; - llvm::raw_string_ostream StrS(Buffer); - std::invoke(Printer, This, std::ref(StrS), Arg); - return Buffer; -} - -template struct NodePrinterBase { - virtual ~NodePrinterBase() = default; - - virtual void printNode(llvm::raw_ostream &OS, N Stmt) const = 0; - - [[nodiscard]] std::string NtoString(N Stmt) const { // NOLINT - return toStringBuilder(&NodePrinterBase::printNode, this, Stmt); - } -}; -template -using NodePrinter = NodePrinterBase; - -template struct DataFlowFactPrinterBase { - virtual ~DataFlowFactPrinterBase() = default; - - virtual void printDataFlowFact(llvm::raw_ostream &OS, D Fact) const = 0; - - [[nodiscard]] std::string DtoString(D Fact) const { // NOLINT - return toStringBuilder(&DataFlowFactPrinterBase::printDataFlowFact, this, - Fact); - } -}; -template -using DataFlowFactPrinter = - DataFlowFactPrinterBase; - -template struct ValuePrinter { - virtual ~ValuePrinter() = default; - - virtual void printValue(llvm::raw_ostream &OS, V Val) const = 0; - - [[nodiscard]] std::string VtoString(V Val) const { // NOLINT - return toStringBuilder(&ValuePrinter::printValue, this, Val); - } -}; - -template struct TypePrinter { - virtual ~TypePrinter() = default; +namespace llvm { +class Value; +class Instruction; +class Function; +} // namespace llvm - virtual void printType(llvm::raw_ostream &OS, T Ty) const = 0; - - [[nodiscard]] std::string TtoString(T Ty) const { // NOLINT - return toStringBuilder(&TypePrinter::printType, this, Ty); +namespace psr { +namespace detail { +template +static constexpr bool IsSomehowPrintable = + has_str_v || is_llvm_printable_v || has_adl_to_string_v; + +template decltype(auto) printSomehow(const T &Val) { + if constexpr (has_str_v) { + return Val.str(); + } else if constexpr (has_adl_to_string_v) { + return adl_to_string(Val); + } else if constexpr (is_llvm_printable_v) { + std::string Str; + llvm::raw_string_ostream ROS(Str); + ROS << Val; + return Str; + } else { + llvm_unreachable( + "All compilable cases should be handled in the if-chain above"); } -}; - -template struct EdgeFactPrinterBase { - using l_t = L; - - virtual ~EdgeFactPrinterBase() = default; - - virtual void printEdgeFact(llvm::raw_ostream &OS, l_t Val) const = 0; +} +} // namespace detail + +/// Stringify the given ICFG node (instruction/statement). +/// +/// Default implementation. Provide your own overload to customize this API for +/// your types +template >> +[[nodiscard]] decltype(auto) NToString(const N &Node) { + return detail::printSomehow(Node); +} - [[nodiscard]] std::string LtoString(l_t Val) const { // NOLINT - return toStringBuilder(&EdgeFactPrinterBase::printEdgeFact, this, Val); - } -}; +/// Stringify the given data-flow fact. +/// +/// Default implementation. Provide your own overload to customize this API for +/// your types +template >> +[[nodiscard]] decltype(auto) DToString(const D &Fact) { + return detail::printSomehow(Fact); +} -template -using EdgeFactPrinter = EdgeFactPrinterBase; +/// Stringify the given edge value. +/// +/// Default implementation. Provide your own overload to customize this API for +/// your types +template >> +[[nodiscard]] decltype(auto) LToString(const L &Value) { + return detail::printSomehow(Value); +} -template struct FunctionPrinter { - using F = typename AnalysisDomainTy::f_t; +/// Stringify the given function. +/// +/// Default implementation. Provide your own overload to customize this API for +/// your types +template >> +[[nodiscard]] std::string FToString(const F &Fun) { + return detail::printSomehow(Fun); +} - virtual ~FunctionPrinter() = default; +// -- specializations - virtual void printFunction(llvm::raw_ostream &OS, F Func) const = 0; +// --- LLVM +// Note: Provide forward declarations here, such that improper usage will +// definitely lead to an error instead of triggering one of the default +// implementations - [[nodiscard]] std::string FtoString(F Func) const { // NOLINT - return toStringBuilder(&FunctionPrinter::printFunction, this, Func); - } -}; +/// Stringify the given LLVM Value. +/// +/// \remark Link phasar_llvm_utils to use this +[[nodiscard]] std::string NToString(const llvm::Value *V); -template struct ContainerPrinter { - virtual ~ContainerPrinter() = default; +/// Stringify the given LLVM Instruction. +/// +/// \remark Link phasar_llvm_utils to use this +[[nodiscard]] std::string NToString(const llvm::Instruction *V); - virtual void printContainer(llvm::raw_ostream &OS, - ContainerTy Container) const = 0; +/// Stringify the given LLVM Value. +/// +/// \remark Link phasar_llvm_utils to use this +[[nodiscard]] std::string DToString(const llvm::Value *V); - [[nodiscard]] std::string - ContainertoString(ContainerTy Container) const { // NOLINT - return toStringBuilder(&ContainerPrinter::printContainer, this, Container); - } -}; +/// Stringify the given LLVM Function. +/// +/// \remark Link phasar_llvm_utils to use this +[[nodiscard]] llvm::StringRef FToString(const llvm::Function *V); } // namespace psr diff --git a/include/phasar/Utils/TypeTraits.h b/include/phasar/Utils/TypeTraits.h index a069bcb5c4..745cc4b42c 100644 --- a/include/phasar/Utils/TypeTraits.h +++ b/include/phasar/Utils/TypeTraits.h @@ -12,6 +12,7 @@ #include "llvm/Support/raw_ostream.h" +#include #include #include #include @@ -19,6 +20,7 @@ #include namespace psr { + // NOLINTBEGIN(readability-identifier-naming) namespace detail { diff --git a/lib/Controller/AnalysisControllerXIDECSTDIOTS.cpp b/lib/Controller/AnalysisControllerXIDECSTDIOTS.cpp index 68cb0c0f42..59bd165343 100644 --- a/lib/Controller/AnalysisControllerXIDECSTDIOTS.cpp +++ b/lib/Controller/AnalysisControllerXIDECSTDIOTS.cpp @@ -15,7 +15,8 @@ namespace psr { void AnalysisController::executeIDECSTDIOTS() { CSTDFILEIOTypeStateDescription TSDesc; - executeIDEAnalysis(&TSDesc, EntryPoints); + executeIDEAnalysis>( + &TSDesc, EntryPoints); } } // namespace psr diff --git a/lib/Controller/AnalysisControllerXIDEOpenSSLTS.cpp b/lib/Controller/AnalysisControllerXIDEOpenSSLTS.cpp index b686680f0b..6c6dba3b45 100644 --- a/lib/Controller/AnalysisControllerXIDEOpenSSLTS.cpp +++ b/lib/Controller/AnalysisControllerXIDEOpenSSLTS.cpp @@ -15,7 +15,8 @@ namespace psr { void AnalysisController::executeIDEOpenSSLTS() { OpenSSLEVPKDFDescription TSDesc; - executeIDEAnalysis(&TSDesc, EntryPoints); + executeIDEAnalysis>( + &TSDesc, EntryPoints); } } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp index 2892959788..02c08a3099 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp @@ -23,6 +23,7 @@ #include "phasar/Pointer/PointsToInfo.h" #include "phasar/Utils/DebugOutput.h" #include "phasar/Utils/Logger.h" +#include "phasar/Utils/Printer.h" #include "phasar/Utils/Utilities.h" #include "llvm/ADT/SmallSet.h" @@ -318,7 +319,7 @@ IDEExtendedTaintAnalysis::getCallFlowFunction(n_t CallStmt, f_t DestFun) { ParamIterator FEnd = DestFun->arg_end(); PHASAR_LOG_LEVEL(DEBUG, "##Call-FF at: " << psr::llvmIRToString(Call) - << " to: " << FtoString(DestFun)); + << " to: " << FToString(DestFun)); for (; FIt != FEnd && It != End; ++FIt, ++It) { auto From = makeFlowFact(It->get()); /// Pointer-Arithetics in the last indirection are irrelevant for @@ -741,26 +742,6 @@ auto IDEExtendedTaintAnalysis::getSummaryEdgeFunction(n_t Curr, d_t CurrNode, // Printing functions: -void IDEExtendedTaintAnalysis::printNode(llvm::raw_ostream &OS, - n_t Inst) const { - OS << llvmIRToString(Inst); -} - -void IDEExtendedTaintAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - d_t Fact) const { - OS << Fact; -} - -void IDEExtendedTaintAnalysis::printEdgeFact(llvm::raw_ostream &OS, - l_t Fact) const { - OS << Fact; -} - -void IDEExtendedTaintAnalysis::printFunction(llvm::raw_ostream &OS, - f_t Fun) const { - OS << (Fun && Fun->hasName() ? Fun->getName() : ""); -} - void IDEExtendedTaintAnalysis::emitTextReport( const SolverResults &SR, llvm::raw_ostream &OS) { OS << "===== IDEExtendedTaintAnalysis-Results =====\n"; @@ -770,9 +751,7 @@ void IDEExtendedTaintAnalysis::emitTextReport( } for (auto &[Inst, LeakSet] : Leaks) { - OS << "At "; - printNode(OS, Inst); - OS << "\n"; + OS << "At " << NToString(Inst) << '\n'; for (const auto &Leak : LeakSet) { OS << "\t" << llvmIRToShortString(Leak) << "\n"; } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp index ae742e9055..b49ecb8720 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp @@ -253,14 +253,10 @@ EdgeFunction IDEGeneralizedLCA::getNormalEdgeFunction( IDEGeneralizedLCA::n_t Curr, IDEGeneralizedLCA::d_t CurrNode, IDEGeneralizedLCA::n_t Succ, IDEGeneralizedLCA::d_t SuccNode) { PHASAR_LOG_LEVEL(DEBUG, "IDEGeneralizedLCA::getNormalEdgeFunction()"); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Curr Inst : " << IDEGeneralizedLCA::NtoString(Curr)); - PHASAR_LOG_LEVEL( - DEBUG, "(D) Curr Node : " << IDEGeneralizedLCA::DtoString(CurrNode)); - PHASAR_LOG_LEVEL(DEBUG, - "(N) Succ Inst : " << IDEGeneralizedLCA::NtoString(Succ)); - PHASAR_LOG_LEVEL( - DEBUG, "(D) Succ Node : " << IDEGeneralizedLCA::DtoString(SuccNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Curr Inst : " << NToString(Curr)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Curr Node : " << DToString(CurrNode)); + PHASAR_LOG_LEVEL(DEBUG, "(N) Succ Inst : " << NToString(Succ)); + PHASAR_LOG_LEVEL(DEBUG, "(D) Succ Node : " << DToString(SuccNode)); // Initialize global variables at entry point if (!isZeroValue(CurrNode) && ICF->isStartPoint(Curr) && isEntryPoint(ICF->getFunctionOf(Curr)->getName().str()) && @@ -474,27 +470,6 @@ EdgeFunction IDEGeneralizedLCA::allTopFunction() { return AlltopFn; } -void IDEGeneralizedLCA::printNode(llvm::raw_ostream &Os, - IDEGeneralizedLCA::n_t Stmt) const { - Os << llvmIRToString(Stmt); -} - -void IDEGeneralizedLCA::printDataFlowFact(llvm::raw_ostream &Os, - IDEGeneralizedLCA::d_t Fact) const { - assert(Fact && "Invalid dataflow fact"); - Os << llvmIRToString(Fact); -} - -void IDEGeneralizedLCA::printFunction(llvm::raw_ostream &Os, - IDEGeneralizedLCA::f_t Func) const { - Os << Func->getName(); -} - -void IDEGeneralizedLCA::printEdgeFact(llvm::raw_ostream &Os, - IDEGeneralizedLCA::l_t L) const { - Os << L; -} - /*void IDEGeneralizedLCA::printIDEReport( llvm::raw_ostream &os, SolverResults AllocatedVars; for (const auto *Stmt : ICF->getAllInstructionsOf(F)) { unsigned Lnr = getLineFromIR(Stmt); - llvm::outs() << "\nIR : " << NtoString(Stmt) << "\nLNR: " << Lnr << '\n'; + llvm::outs() << "\nIR : " << NToString(Stmt) << "\nLNR: " << Lnr << '\n'; // We skip statements with no source code mapping if (Lnr == 0) { llvm::outs() << "Skipping this stmt!\n"; @@ -622,15 +597,15 @@ IDEGeneralizedLCA::lca_results_t IDEGeneralizedLCA::getLCAResults( } else { // It's not a terminator inst, hence it has only a single successor const auto *Succ = ICF->getSuccsOf(Stmt)[0]; - llvm::outs() << "Succ stmt: " << NtoString(Succ) << '\n'; + llvm::outs() << "Succ stmt: " << NToString(Succ) << '\n'; Results = SR.resultsAt(Succ, true); } // stripBottomResults(results); std::set ValidVarsAtStmt; for (const auto &Res : Results) { auto VarName = getVarNameFromIR(Res.first); - llvm::outs() << " D: " << DtoString(Res.first) - << " | V: " << VtoString(Res.second) + llvm::outs() << " D: " << DToString(Res.first) + << " | V: " << LToString(Res.second) << " | Var: " << VarName << '\n'; if (!VarName.empty()) { // Only store/overwrite values of variables from allocas or @@ -693,13 +668,6 @@ bool IDEGeneralizedLCA::isEntryPoint(const std::string &Name) const { return Name == "main"; } -template std::string IDEGeneralizedLCA::VtoString(V Val) { - std::string Buffer; - llvm::raw_string_ostream Ss(Buffer); - Ss << Val; - return Ss.str(); -} - bool IDEGeneralizedLCA::isStringConstructor(const llvm::Function *F) { return (ICF->getSpecialMemberFunctionType(F) == SpecialMemberFunctionType::Constructor && diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index 40de55d9bd..a8aa6e8240 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -564,26 +564,6 @@ IDELinearConstantAnalysis::getSummaryEdgeFunction(n_t Curr, d_t CurrNode, return EdgeIdentity{}; } -void IDELinearConstantAnalysis::printNode(llvm::raw_ostream &OS, - n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IDELinearConstantAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - d_t Fact) const { - OS << llvmIRToShortString(Fact); -} - -void IDELinearConstantAnalysis::printFunction(llvm::raw_ostream &OS, - f_t Func) const { - OS << Func->getName(); -} - -void IDELinearConstantAnalysis::printEdgeFact(llvm::raw_ostream &OS, - l_t L) const { - OS << L; -} - void IDELinearConstantAnalysis::emitTextReport( const SolverResults &SR, llvm::raw_ostream &OS) { OS << "\n====================== IDE-Linear-Constant-Analysis Report " @@ -600,11 +580,11 @@ void IDELinearConstantAnalysis::emitTextReport( auto Results = SR.resultsAt(Stmt, true); stripBottomResults(Results); if (!Results.empty()) { - OS << "At IR statement: " << NtoString(Stmt) << '\n'; + OS << "At IR statement: " << NToString(Stmt) << '\n'; for (auto Res : Results) { if (!Res.second.isBottom()) { - OS << " Fact: " << DtoString(Res.first) - << "\n Value: " << LtoString(Res.second) << '\n'; + OS << " Fact: " << DToString(Res.first) + << "\n Value: " << LToString(Res.second) << '\n'; } } OS << '\n'; @@ -648,7 +628,7 @@ IDELinearConstantAnalysis::getLCAResults(SolverResults SR) { std::set AllocatedVars; for (const auto *Stmt : ICF->getAllInstructionsOf(F)) { unsigned Lnr = getLineFromIR(Stmt); - llvm::outs() << "\nIR : " << NtoString(Stmt) << "\nLNR: " << Lnr << '\n'; + llvm::outs() << "\nIR : " << NToString(Stmt) << "\nLNR: " << Lnr << '\n'; // We skip statements with no source code mapping if (Lnr == 0) { llvm::outs() << "Skipping this stmt!\n"; @@ -679,15 +659,15 @@ IDELinearConstantAnalysis::getLCAResults(SolverResults SR) { } else { // It's not a terminator inst, hence it has only a single successor const auto *Succ = ICF->getSuccsOf(Stmt)[0]; - llvm::outs() << "Succ stmt: " << NtoString(Succ) << '\n'; + llvm::outs() << "Succ stmt: " << NToString(Succ) << '\n'; Results = SR.resultsAt(Succ, true); } stripBottomResults(Results); std::set ValidVarsAtStmt; for (auto Res : Results) { auto VarName = getVarNameFromIR(Res.first); - llvm::outs() << " D: " << DtoString(Res.first) - << " | V: " << LtoString(Res.second) + llvm::outs() << " D: " << DToString(Res.first) + << " | V: " << LToString(Res.second) << " | Var: " << VarName << '\n'; if (!VarName.empty()) { // Only store/overwrite values of variables from allocas or globals diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp index fcc2242f86..d3cff2862a 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEProtoAnalysis.cpp @@ -141,24 +141,4 @@ EdgeFunction IDEProtoAnalysis::allTopFunction() { return AllTop{nullptr}; } -void IDEProtoAnalysis::printNode(llvm::raw_ostream &OS, - IDEProtoAnalysis::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IDEProtoAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - IDEProtoAnalysis::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IDEProtoAnalysis::printFunction(llvm::raw_ostream &OS, - IDEProtoAnalysis::f_t Func) const { - OS << Func->getName(); -} - -void IDEProtoAnalysis::printEdgeFact(llvm::raw_ostream &OS, - IDEProtoAnalysis::l_t L) const { - OS << llvmIRToString(L); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp index 2ba44060d2..a068537877 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESecureHeapPropagation.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" #include #include @@ -113,31 +114,6 @@ bool IDESecureHeapPropagation::isZeroValue(d_t Fact) const noexcept { return Fact == SecureHeapFact::ZERO; } -void IDESecureHeapPropagation::printNode(llvm::raw_ostream &Os, - n_t Stmt) const { - Os << llvmIRToString(Stmt); -} - -void IDESecureHeapPropagation::printDataFlowFact(llvm::raw_ostream &Os, - d_t Fact) const { - switch (Fact) { - case SecureHeapFact::ZERO: - Os << "ZERO"; - break; - case SecureHeapFact::INITIALIZED: - Os << "INITIALIZED"; - break; - default: - assert(false && "Invalid dataflow-fact"); - break; - } -} - -void IDESecureHeapPropagation::printFunction(llvm::raw_ostream &Os, - f_t F) const { - Os << llvm::demangle(F->getName().str()); -} - // in addition provide specifications for the IDE parts EdgeFunction @@ -187,24 +163,6 @@ IDESecureHeapPropagation::getSummaryEdgeFunction(n_t /*CallSite*/, return nullptr; } -void IDESecureHeapPropagation::printEdgeFact(llvm::raw_ostream &Os, - l_t L) const { - switch (L) { - case l_t::BOT: - Os << "BOT"; - break; - case l_t::INITIALIZED: - Os << "INITIALIZED"; - break; - case l_t::TOP: - Os << "TOP"; - break; - default: - assert(false && "Invalid edge fact"); - break; - } -} - void IDESecureHeapPropagation::emitTextReport( const SolverResults &SR, llvm::raw_ostream &Os) { LLVMBasedCFG CFG; @@ -217,11 +175,11 @@ void IDESecureHeapPropagation::emitTextReport( auto Results = SR.resultsAt(Stmt, true); if (!Results.empty()) { - Os << "At IR statement: " << NtoString(Stmt) << '\n'; + Os << "At IR statement: " << NToString(Stmt) << '\n'; for (auto Res : Results) { - Os << " Fact: " << DtoString(Res.first) - << "\n Value: " << LtoString(Res.second) << '\n'; + Os << " Fact: " << DToString(Res.first) + << "\n Value: " << LToString(Res.second) << '\n'; } Os << '\n'; } @@ -231,3 +189,25 @@ void IDESecureHeapPropagation::emitTextReport( } } // namespace psr + +llvm::StringRef psr::DToString(SecureHeapFact Fact) noexcept { + switch (Fact) { + case SecureHeapFact::ZERO: + return "ZERO"; + case SecureHeapFact::INITIALIZED: + return "INITIALIZED"; + } + llvm_unreachable("Invalid dataflow-fact"); +} + +llvm::StringRef psr::LToString(SecureHeapValue Val) noexcept { + switch (Val) { + case SecureHeapValue::BOT: + return "BOT"; + case SecureHeapValue::INITIALIZED: + return "INITIALIZED"; + case SecureHeapValue::TOP: + return "TOP"; + } + llvm_unreachable("Invalid edge fact"); +} diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp index bb759d32ef..1324d61a55 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDESolverTest.cpp @@ -143,24 +143,4 @@ EdgeFunction IDESolverTest::allTopFunction() { return AllTop{nullptr}; } -void IDESolverTest::printNode(llvm::raw_ostream &OS, - IDESolverTest::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IDESolverTest::printDataFlowFact(llvm::raw_ostream &OS, - IDESolverTest::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IDESolverTest::printFunction(llvm::raw_ostream &OS, - IDESolverTest::f_t Func) const { - OS << Func->getName(); -} - -void IDESolverTest::printEdgeFact(llvm::raw_ostream &OS, - IDESolverTest::l_t /*L*/) const { - OS << "empty V test"; -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp index cb5c01d627..3f20b5d979 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp @@ -34,179 +34,23 @@ #include #include -namespace psr { +namespace psr::detail { -/// -/// -/// TODO: Make Bottom common across all implementations of TypeStateDescription! -/// then we can factor it out of all edge functions making some of them -/// applicable for small-object optimization! -/// -/// - -// customize the edge function composer -struct TSEdgeFunctionComposer - : EdgeFunctionComposer { - IDETypeStateAnalysisDomain::l_t BotElement{}; - - static EdgeFunction - join(EdgeFunctionRef This, - const EdgeFunction &OtherFunction) { - if (auto Default = defaultJoinOrNull(This, OtherFunction)) { - return Default; - } - - return AllBottom{This->BotElement}; - } -}; - -struct TSEdgeFunction { - const TypeStateDescription *TSD; - // XXX: Do we really need a string here? Can't we just use an integer or sth - // else that is cheap? - std::string Token; - const llvm::CallBase *CallSite; - - using l_t = IDETypeStateAnalysisDomain ::l_t; - - [[nodiscard]] l_t computeTarget(l_t Source) const { - - // assert((Source != TSD->top()) && "Error: call computeTarget with TOP\n"); - - auto CurrentState = TSD->getNextState( - Token, Source == TSD->top() ? TSD->uninit() : Source, CallSite); - PHASAR_LOG_LEVEL(DEBUG, "State machine transition: (" - << Token << " , " << TSD->stateToString(Source) - << ") -> " << TSD->stateToString(CurrentState)); - return CurrentState; - } - - static EdgeFunction compose(EdgeFunctionRef This, - const EdgeFunction &SecondFunction) { - if (auto Default = defaultComposeOrNull(This, SecondFunction)) { - return Default; - } - - return TSEdgeFunctionComposer{{This, SecondFunction}, This->TSD->bottom()}; - } - - static EdgeFunction join(EdgeFunctionRef This, - const EdgeFunction &OtherFunction) { - if (auto Default = defaultJoinOrNull(This, OtherFunction)) { - return Default; - } - - return AllBottom{This->TSD->bottom()}; - } - - bool operator==(const TSEdgeFunction &Other) const { - return CallSite == Other.CallSite && Token == Other.Token; - } - - friend llvm::raw_ostream &print(llvm::raw_ostream &OS, - const TSEdgeFunction &TSE) { - return OS << "TSEF(" << TSE.Token << " at " - << llvmIRToShortString(TSE.CallSite) << ")"; - } -}; - -struct TSConstant : ConstantEdgeFunction { - const TypeStateDescription *TSD{}; - - /// XXX: Cannot default compose() and join(), because l_t does not implement - /// JoinLatticeTraits (because bottom value is not constant) - template - static EdgeFunction compose(EdgeFunctionRef This, - const EdgeFunction &SecondFunction) { - - if (auto Default = defaultComposeOrNull(This, SecondFunction)) { - return Default; - } - - auto Ret = SecondFunction.computeTarget(This->Value); - if (Ret == This->Value) { - return This; - } - if (Ret == This->TSD->bottom()) { - return AllBottom{Ret}; - } - - return TSConstant{{Ret}, This->TSD}; - } - - template - static EdgeFunction join(EdgeFunctionRef This, - const EdgeFunction &OtherFunction) { - if (auto Default = defaultJoinOrNull(This, OtherFunction)) { - return Default; - } - - const auto *TSD = This->TSD; - if (const auto *C = llvm::dyn_cast(OtherFunction)) { - if (C->Value == This->Value || C->Value == TSD->top()) { - return This; - } - if (This->Value == TSD->top()) { - return OtherFunction; - } - } - return AllBottom{TSD->bottom()}; - } -}; - -bool operator==(ByConstRef LHS, - ByConstRef RHS) noexcept { - return LHS.Value == RHS.Value; -} - -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - ByConstRef EF) { - return OS << "TSConstant[" << EF.TSD->stateToString(EF.Value) << "]"; -} - -IDETypeStateAnalysis::IDETypeStateAnalysis(const LLVMProjectIRDB *IRDB, - LLVMAliasInfoRef PT, - const TypeStateDescription *TSD, - std::vector EntryPoints) - : IDETabulationProblem(IRDB, std::move(EntryPoints), createZeroValue()), - TSD(TSD), PT(PT) { - assert(TSD != nullptr); - assert(PT); -} - -// Start formulating our analysis by specifying the parts required for IFDS - -IDETypeStateAnalysis::FlowFunctionPtrType -IDETypeStateAnalysis::getNormalFlowFunction( - IDETypeStateAnalysis::n_t Curr, IDETypeStateAnalysis::n_t /*Succ*/) { +auto IDETypeStateAnalysisBase::getNormalFlowFunction(n_t Curr, n_t /*Succ*/) + -> FlowFunctionPtrType { // Check if Alloca's type matches the target type. If so, generate from zero // value. if (const auto *Alloca = llvm::dyn_cast(Curr)) { if (hasMatchingType(Alloca)) { - return generateFromZero(Alloca); + return this->generateFromZero(Alloca); } } - // Check load instructions for target type. Generate from the loaded value and - // kill the load instruction if it was generated previously (strong update!). + // Check load instructions for target type. Generate from the loaded value + // and kill the load instruction if it was generated previously (strong + // update!). if (const auto *Load = llvm::dyn_cast(Curr)) { if (hasMatchingType(Load)) { - struct TSFlowFunction : FlowFunction { - const llvm::LoadInst *Load; - - TSFlowFunction(const llvm::LoadInst *L) : Load(L) {} - ~TSFlowFunction() override = default; - std::set - computeTargets(IDETypeStateAnalysis::d_t Source) override { - if (Source == Load) { - return {}; - } - if (Source == Load->getPointerOperand()) { - return {Source, Load}; - } - return {Source}; - } - }; - return std::make_shared(Load); + return transferFlow(Load, Load->getPointerOperand()); } } if (const auto *Gep = llvm::dyn_cast(Curr)) { @@ -220,52 +64,42 @@ IDETypeStateAnalysis::getNormalFlowFunction( } } // Check store instructions for target type. Perform a strong update, i.e. - // kill the alloca pointed to by the pointer-operand and all alloca's related - // to the value-operand and then generate them from the value-operand. + // kill the alloca pointed to by the pointer-operand and all alloca's + // related to the value-operand and then generate them from the + // value-operand. if (const auto *Store = llvm::dyn_cast(Curr)) { if (hasMatchingType(Store)) { auto RelevantAliasesAndAllocas = getLocalAliasesAndAllocas( Store->getPointerOperand(), // pointer- or value operand??? // Store->getValueOperand(), - Curr->getParent()->getParent()->getName().str()); - - struct TSFlowFunction : FlowFunction { - const llvm::StoreInst *Store; - std::set AliasesAndAllocas; - TSFlowFunction(const llvm::StoreInst *S, - std::set AA) - : Store(S), AliasesAndAllocas(std::move(AA)) {} - ~TSFlowFunction() override = default; - std::set - computeTargets(IDETypeStateAnalysis::d_t Source) override { - // We kill all relevant loacal aliases and alloca's - if (Source != Store->getValueOperand() && - // AliasesAndAllocas.find(Source) != AliasesAndAllocas.end() - // Is simple comparison sufficient? - Source == Store->getPointerOperand()) { - return {}; - } - // Generate all local aliases and relevant alloca's from the stored - // value - if (Source == Store->getValueOperand()) { - AliasesAndAllocas.insert(Source); - return AliasesAndAllocas; - } - return {Source}; - } - }; - return std::make_shared(Store, RelevantAliasesAndAllocas); + Curr->getFunction()->getName().str()); + + RelevantAliasesAndAllocas.insert(Store->getValueOperand()); + return lambdaFlow( + [Store, AliasesAndAllocas = std::move(RelevantAliasesAndAllocas)]( + d_t Source) -> container_type { + // We kill all relevant loacal aliases and alloca's + if (Source == Store->getPointerOperand()) { + // XXX: later kill must-aliases too + return {}; + } + // Generate all local aliases and relevant alloca's from the + // stored value + if (Source == Store->getValueOperand()) { + return AliasesAndAllocas; + } + return {Source}; + }); } } return identityFlow(); } -IDETypeStateAnalysis::FlowFunctionPtrType -IDETypeStateAnalysis::getCallFlowFunction(IDETypeStateAnalysis::n_t CallSite, - IDETypeStateAnalysis::f_t DestFun) { +auto IDETypeStateAnalysisBase::getCallFlowFunction(n_t CallSite, f_t DestFun) + -> FlowFunctionPtrType { // Kill all data-flow facts if we hit a function of the target API. // Those functions are modled within Call-To-Return. - if (TSD->isAPIFunction(llvm::demangle(DestFun->getName().str()))) { + if (isAPIFunction(llvm::demangle(DestFun->getName().str()))) { return killAllFlows(); } // Otherwise, if we have an ordinary function call, we can just use the @@ -276,128 +110,87 @@ IDETypeStateAnalysis::getCallFlowFunction(IDETypeStateAnalysis::n_t CallSite, llvm::report_fatal_error("callSite not a CallInst nor a InvokeInst"); } -IDETypeStateAnalysis::FlowFunctionPtrType -IDETypeStateAnalysis::getRetFlowFunction( - IDETypeStateAnalysis::n_t CallSite, IDETypeStateAnalysis::f_t CalleeFun, - IDETypeStateAnalysis::n_t ExitStmt, IDETypeStateAnalysis::n_t /*RetSite*/) { - // Besides mapping the formal parameter back into the actual parameter and - // propagating the return value into the caller context, we also propagate - // all related alloca's of the formal parameter and the return value. - struct TSFlowFunction : FlowFunction { - const llvm::CallBase *CallSite; - const llvm::Function *CalleeFun; - const llvm::ReturnInst *ExitSite; - IDETypeStateAnalysis *Analysis; - std::vector Actuals; - std::vector Formals; - TSFlowFunction(const llvm::CallBase *CallSite, - const llvm::Function *CalleeFun, - const llvm::Instruction *ExitSite, - IDETypeStateAnalysis *Analysis) - : CallSite(CallSite), CalleeFun(CalleeFun), - ExitSite(llvm::dyn_cast(ExitSite)), - Analysis(Analysis) { - // Set up the actual parameters - for (unsigned Idx = 0; Idx < CallSite->arg_size(); ++Idx) { - Actuals.push_back(CallSite->getArgOperand(Idx)); - } - // Set up the formal parameters - for (unsigned Idx = 0; Idx < CalleeFun->arg_size(); ++Idx) { - Formals.push_back(getNthFunctionArgument(CalleeFun, Idx)); - } - } - - ~TSFlowFunction() override = default; +auto IDETypeStateAnalysisBase::getRetFlowFunction(n_t CallSite, f_t CalleeFun, + n_t ExitStmt, n_t /*RetSite*/) + -> FlowFunctionPtrType { - std::set - computeTargets(IDETypeStateAnalysis::d_t Source) override { - if (!LLVMZeroValue::isLLVMZeroValue(Source)) { - std::set Res; - // Handle C-style varargs functions - if (CalleeFun->isVarArg() && !CalleeFun->isDeclaration()) { - const llvm::Instruction *AllocVarArg; - // Find the allocation of %struct.__va_list_tag - for (const auto &BB : *CalleeFun) { - for (const auto &I : BB) { - if (const auto *Alloc = llvm::dyn_cast(&I)) { - if (Alloc->getAllocatedType()->isArrayTy() && - Alloc->getAllocatedType()->getArrayNumElements() > 0 && - Alloc->getAllocatedType() + /// TODO: Implement return-POI in LLVMFlowFunctions.h + return lambdaFlow([this, CalleeFun, CS = llvm::cast(CallSite), + Ret = llvm::dyn_cast(ExitStmt)]( + d_t Source) -> container_type { + if (LLVMZeroValue::isLLVMZeroValue(Source)) { + return {Source}; + } + container_type Res; + // Handle C-style varargs functions + if (CalleeFun->isVarArg() && !CalleeFun->isDeclaration()) { + const llvm::Instruction *AllocVarArg; + // Find the allocation of %struct.__va_list_tag + for (const auto &BB : *CalleeFun) { + for (const auto &I : BB) { + if (const auto *Alloc = llvm::dyn_cast(&I)) { + if (Alloc->getAllocatedType()->isArrayTy() && + Alloc->getAllocatedType()->getArrayNumElements() > 0 && + Alloc->getAllocatedType() + ->getArrayElementType() + ->isStructTy() && + Alloc->getAllocatedType() ->getArrayElementType() - ->isStructTy() && - Alloc->getAllocatedType() - ->getArrayElementType() - ->getStructName() == "struct.__va_list_tag") { - AllocVarArg = Alloc; - // TODO break out this nested loop earlier (without goto ;-) - } - } + ->getStructName() == "struct.__va_list_tag") { + AllocVarArg = Alloc; + // TODO break out this nested loop earlier (without goto ;-) } } - // Generate the varargs things by using an over-approximation - if (Source == AllocVarArg) { - for (unsigned Idx = Formals.size(); Idx < Actuals.size(); ++Idx) { - Res.insert(Actuals[Idx]); - } - } - } - // Handle ordinary case - // Map formal parameter into corresponding actual parameter. - for (unsigned Idx = 0; Idx < Formals.size(); ++Idx) { - if (Source == Formals[Idx]) { - Res.insert(Actuals[Idx]); // corresponding actual - } - } - // Collect the return value - if (Source == ExitSite->getReturnValue()) { - Res.insert(CallSite); } - // Collect all relevant alloca's to map into caller context - std::set RelAllocas; - for (const auto *Fact : Res) { - auto Allocas = Analysis->getRelevantAllocas(Fact); - RelAllocas.insert(Allocas.begin(), Allocas.end()); + } + // Generate the varargs things by using an over-approximation + if (Source == AllocVarArg) { + for (unsigned Idx = CalleeFun->arg_size(); Idx < CS->arg_size(); + ++Idx) { + Res.insert(CS->getArgOperand(Idx)); } - Res.insert(RelAllocas.begin(), RelAllocas.end()); - return Res; } - return {Source}; } - }; - return std::make_shared(llvm::cast(CallSite), - CalleeFun, ExitStmt, this); + // Handle ordinary case + // Map formal parameter into corresponding actual parameter. + for (auto [Formal, Actual] : llvm::zip(CalleeFun->args(), CS->args())) { + if (Source == &Formal) { + Res.insert(Actual); // corresponding actual + } + } + + // Collect the return value + if (Ret && Source == Ret->getReturnValue()) { + Res.insert(CS); + } + + // Collect all relevant alloca's to map into caller context + { + container_type RelAllocas; + for (const auto *Fact : Res) { + const auto &Allocas = getRelevantAllocas(Fact); + RelAllocas.insert(Allocas.begin(), Allocas.end()); + } + Res.insert(RelAllocas.begin(), RelAllocas.end()); + } + + return Res; + }); } -IDETypeStateAnalysis::FlowFunctionPtrType -IDETypeStateAnalysis::getCallToRetFlowFunction( - IDETypeStateAnalysis::n_t CallSite, IDETypeStateAnalysis::n_t /*RetSite*/, - llvm::ArrayRef Callees) { +auto IDETypeStateAnalysisBase::getCallToRetFlowFunction( + n_t CallSite, n_t /*RetSite*/, llvm::ArrayRef Callees) + -> FlowFunctionPtrType { const auto *CS = llvm::cast(CallSite); for (const auto *Callee : Callees) { std::string DemangledFname = llvm::demangle(Callee->getName().str()); // Generate the return value of factory functions from zero value - if (TSD->isFactoryFunction(DemangledFname)) { - struct TSFlowFunction : FlowFunction { - IDETypeStateAnalysis::d_t CS, ZeroValue; - - TSFlowFunction(IDETypeStateAnalysis::d_t CS, - IDETypeStateAnalysis::d_t Z) - : CS(CS), ZeroValue(Z) {} - ~TSFlowFunction() override = default; - std::set - computeTargets(IDETypeStateAnalysis::d_t Source) override { - if (Source == CS) { - return {}; - } - if (Source == ZeroValue) { - return {Source, CS}; - } - return {Source}; - } - }; - return std::make_shared(CS, getZeroValue()); + if (isFactoryFunction(DemangledFname)) { + return this->generateFromZero(CS); } + /// XXX: Revisit this: + // Handle all functions that are not modeld with special semantics. // Kill actual parameters of target type and all its aliases // and the corresponding alloca(s) as these data-flow facts are @@ -408,7 +201,7 @@ IDETypeStateAnalysis::getCallToRetFlowFunction( // not be killed during call-to-return, since it is not safe to assume // that the return value will be used afterwards, i.e. is stored to memory // pointed to by related alloca's. - if (!TSD->isAPIFunction(DemangledFname) && !Callee->isDeclaration()) { + if (!isAPIFunction(DemangledFname) && !Callee->isDeclaration()) { for (const auto &Arg : CS->args()) { if (hasMatchingType(Arg)) { return killManyFlows(getWMAliasesAndAllocas(Arg.get())); @@ -419,199 +212,37 @@ IDETypeStateAnalysis::getCallToRetFlowFunction( return identityFlow(); } -IDETypeStateAnalysis::FlowFunctionPtrType -IDETypeStateAnalysis::getSummaryFlowFunction( - IDETypeStateAnalysis::n_t /*CallSite*/, - IDETypeStateAnalysis::f_t /*DestFun*/) { - return nullptr; -} - -InitialSeeds -IDETypeStateAnalysis::initialSeeds() { - // just start in main() - return createDefaultSeeds(); -} - -IDETypeStateAnalysis::d_t IDETypeStateAnalysis::createZeroValue() const { - // create a special value to represent the zero value! - return LLVMZeroValue::getInstance(); -} - -bool IDETypeStateAnalysis::isZeroValue( - IDETypeStateAnalysis::d_t Fact) const noexcept { - return LLVMZeroValue::isLLVMZeroValue(Fact); -} - -// in addition provide specifications for the IDE parts - -struct TSAllocaEF : TSConstant { - const llvm::AllocaInst *Alloca; - TSAllocaEF(const TypeStateDescription *Tsd, - const llvm::AllocaInst *Alloca) noexcept - : TSConstant{{Tsd->uninit()}, Tsd}, Alloca(Alloca) {} - - friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const TSAllocaEF &TSA) { - return OS << "Alloca(" << llvmIRToShortString(TSA.Alloca) << ")"; - } -}; - -auto IDETypeStateAnalysis::getNormalEdgeFunction( - IDETypeStateAnalysis::n_t Curr, IDETypeStateAnalysis::d_t CurrNode, - IDETypeStateAnalysis::n_t /*Succ*/, IDETypeStateAnalysis::d_t SuccNode) - -> EdgeFunction { - // Set alloca instructions of target type to uninitialized. - if (const auto *Alloca = llvm::dyn_cast(Curr)) { - if (hasMatchingType(Alloca)) { - if (CurrNode == getZeroValue() && SuccNode == Alloca) { - return TSAllocaEF(TSD, Alloca); - } - } - } - return EdgeIdentity{}; -} - -auto IDETypeStateAnalysis::getCallEdgeFunction( - IDETypeStateAnalysis::n_t /*CallSite*/, - IDETypeStateAnalysis::d_t /*SrcNode*/, - IDETypeStateAnalysis::f_t /*DestinationFunction*/, - IDETypeStateAnalysis::d_t /*DestNode*/) -> EdgeFunction { - return EdgeIdentity{}; -} - -auto IDETypeStateAnalysis::getReturnEdgeFunction( - IDETypeStateAnalysis::n_t /*CallSite*/, - IDETypeStateAnalysis::f_t /*CalleeFunction*/, - IDETypeStateAnalysis::n_t /*ExitSite*/, - IDETypeStateAnalysis::d_t /*ExitNode*/, - IDETypeStateAnalysis::n_t /*ReSite*/, IDETypeStateAnalysis::d_t /*RetNode*/) - -> EdgeFunction { - return EdgeIdentity{}; -} - -auto IDETypeStateAnalysis::getCallToRetEdgeFunction( - IDETypeStateAnalysis::n_t CallSite, IDETypeStateAnalysis::d_t CallNode, - IDETypeStateAnalysis::n_t /*RetSite*/, - IDETypeStateAnalysis::d_t RetSiteNode, llvm::ArrayRef Callees) - -> EdgeFunction { - const auto *CS = llvm::cast(CallSite); - for (const auto *Callee : Callees) { - std::string DemangledFname = llvm::demangle(Callee->getName().str()); - - // For now we assume that we can only generate from the return value. - // We apply the same edge function for the return value, i.e. callsite. - if (TSD->isFactoryFunction(DemangledFname)) { - PHASAR_LOG_LEVEL(DEBUG, "Processing factory function"); - if (isZeroValue(CallNode) && RetSiteNode == CS) { - return TSConstant{ - {TSD->getNextState(DemangledFname, TSD->uninit(), CS)}, TSD}; - } - } - - // For every consuming parameter and all its aliases and relevant alloca's - // we apply the same edge function. - if (TSD->isConsumingFunction(DemangledFname)) { - PHASAR_LOG_LEVEL(DEBUG, "Processing consuming function"); - for (auto Idx : TSD->getConsumerParamIdx(DemangledFname)) { - std::set AliasAndAllocas = - getWMAliasesAndAllocas(CS->getArgOperand(Idx)); - - if (CallNode == RetSiteNode && - AliasAndAllocas.find(CallNode) != AliasAndAllocas.end()) { - return TSEdgeFunction{TSD, DemangledFname, CS}; - } - } - } - } - return EdgeIdentity{}; -} - -auto IDETypeStateAnalysis::getSummaryEdgeFunction( - IDETypeStateAnalysis::n_t /*CallSite*/, - IDETypeStateAnalysis::d_t /*CallNode*/, - IDETypeStateAnalysis::n_t /*RetSite*/, - IDETypeStateAnalysis::d_t /*RetSiteNode*/) -> EdgeFunction { +auto IDETypeStateAnalysisBase::getSummaryFlowFunction(n_t /*CallSite*/, + f_t /*DestFun*/) + -> FlowFunctionPtrType { return nullptr; } -IDETypeStateAnalysis::l_t IDETypeStateAnalysis::topElement() { - return TSD->top(); -} - -IDETypeStateAnalysis::l_t IDETypeStateAnalysis::bottomElement() { - return TSD->bottom(); -} - -IDETypeStateAnalysis::l_t -IDETypeStateAnalysis::join(IDETypeStateAnalysis::l_t Lhs, - IDETypeStateAnalysis::l_t Rhs) { - if (Lhs == Rhs) { - return Lhs; - } - if (Lhs == TSD->top()) { - return Rhs; - } - if (Rhs == TSD->top()) { - return Lhs; - } - return TSD->bottom(); -} - -auto IDETypeStateAnalysis::allTopFunction() -> EdgeFunction { - return AllTop{TSD->top()}; -} - -void IDETypeStateAnalysis::printNode(llvm::raw_ostream &OS, n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IDETypeStateAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IDETypeStateAnalysis::printFunction(llvm::raw_ostream &OS, - IDETypeStateAnalysis::f_t Func) const { - OS << Func->getName(); -} - -void IDETypeStateAnalysis::printEdgeFact(llvm::raw_ostream &OS, - IDETypeStateAnalysis::l_t L) const { - OS << TSD->stateToString(L); -} - -std::set -IDETypeStateAnalysis::getRelevantAllocas(IDETypeStateAnalysis::d_t V) { +auto IDETypeStateAnalysisBase::getRelevantAllocas(d_t V) -> container_type { if (RelevantAllocaCache.find(V) != RelevantAllocaCache.end()) { return RelevantAllocaCache[V]; } auto AliasSet = getWMAliasSet(V); - std::set RelevantAllocas; - PHASAR_LOG_LEVEL(DEBUG, "Compute relevant alloca's of " - << IDETypeStateAnalysis::DtoString(V)); + container_type RelevantAllocas; + PHASAR_LOG_LEVEL(DEBUG, "Compute relevant alloca's of " << DToString(V)); for (const auto *Alias : AliasSet) { - PHASAR_LOG_LEVEL(DEBUG, - "Alias: " << IDETypeStateAnalysis::DtoString(Alias)); + PHASAR_LOG_LEVEL(DEBUG, "Alias: " << DToString(Alias)); // Collect the pointer operand of a aliased load instruciton if (const auto *Load = llvm::dyn_cast(Alias)) { if (hasMatchingType(Alias)) { - PHASAR_LOG_LEVEL(DEBUG, - " -> Alloca: " << IDETypeStateAnalysis::DtoString( - Load->getPointerOperand())); + PHASAR_LOG_LEVEL( + DEBUG, " -> Alloca: " << DToString(Load->getPointerOperand())); RelevantAllocas.insert(Load->getPointerOperand()); } } else { // For all other types of aliases, e.g. callsites, function arguments, // we check store instructions where thoses aliases are value operands. for (const auto *User : Alias->users()) { - PHASAR_LOG_LEVEL(DEBUG, - " User: " << IDETypeStateAnalysis::DtoString(User)); + PHASAR_LOG_LEVEL(DEBUG, " User: " << DToString(User)); if (const auto *Store = llvm::dyn_cast(User)) { if (hasMatchingType(Store)) { - PHASAR_LOG_LEVEL( - DEBUG, " -> Alloca: " << IDETypeStateAnalysis::DtoString( - Store->getPointerOperand())); + PHASAR_LOG_LEVEL(DEBUG, " -> Alloca: " << DToString( + Store->getPointerOperand())); RelevantAllocas.insert(Store->getPointerOperand()); } } @@ -624,11 +255,9 @@ IDETypeStateAnalysis::getRelevantAllocas(IDETypeStateAnalysis::d_t V) { return RelevantAllocas; } -std::set -IDETypeStateAnalysis::getWMAliasSet(IDETypeStateAnalysis::d_t V) { +auto IDETypeStateAnalysisBase::getWMAliasSet(d_t V) -> container_type { if (AliasCache.find(V) != AliasCache.end()) { - std::set AliasSet(AliasCache[V].begin(), - AliasCache[V].end()); + container_type AliasSet(AliasCache[V].begin(), AliasCache[V].end()); return AliasSet; } auto PTS = PT.getAliasSet(V); @@ -637,28 +266,25 @@ IDETypeStateAnalysis::getWMAliasSet(IDETypeStateAnalysis::d_t V) { AliasCache[Alias] = *PTS; } } - std::set AliasSet(PTS->begin(), PTS->end()); + container_type AliasSet(PTS->begin(), PTS->end()); return AliasSet; } -std::set -IDETypeStateAnalysis::getWMAliasesAndAllocas(IDETypeStateAnalysis::d_t V) { - std::set AliasAndAllocas; - std::set RelevantAllocas = getRelevantAllocas(V); - std::set Aliases = getWMAliasSet(V); +auto IDETypeStateAnalysisBase::getWMAliasesAndAllocas(d_t V) -> container_type { + container_type AliasAndAllocas; + container_type RelevantAllocas = getRelevantAllocas(V); + container_type Aliases = getWMAliasSet(V); AliasAndAllocas.insert(Aliases.begin(), Aliases.end()); AliasAndAllocas.insert(RelevantAllocas.begin(), RelevantAllocas.end()); return AliasAndAllocas; } -std::set -IDETypeStateAnalysis::getLocalAliasesAndAllocas(IDETypeStateAnalysis::d_t V, - const std::string & /*Fname*/) { - std::set AliasAndAllocas; - std::set RelevantAllocas = getRelevantAllocas(V); - std::set - Aliases; // = - // IRDB->getAliasGraph(Fname)->getAliasSet(V); +auto IDETypeStateAnalysisBase::getLocalAliasesAndAllocas( + d_t V, llvm::StringRef /*Fname*/) -> container_type { + container_type AliasAndAllocas; + container_type RelevantAllocas = getRelevantAllocas(V); + container_type Aliases; // = + // IRDB->getAliasGraph(Fname)->getAliasSet(V); for (const auto *Alias : Aliases) { if (hasMatchingType(Alias)) { AliasAndAllocas.insert(Alias); @@ -668,45 +294,38 @@ IDETypeStateAnalysis::getLocalAliasesAndAllocas(IDETypeStateAnalysis::d_t V, AliasAndAllocas.insert(RelevantAllocas.begin(), RelevantAllocas.end()); return AliasAndAllocas; } -bool hasMatchingTypeName(const llvm::Type *Ty, const std::string &Pattern) { + +bool IDETypeStateAnalysisBase::hasMatchingTypeName(const llvm::Type *Ty) { if (const auto *StructTy = llvm::dyn_cast(Ty)) { - return StructTy->getName().contains(Pattern); + return isTypeNameOfInterest(StructTy->getName()); } // primitive type std::string Str; llvm::raw_string_ostream S(Str); S << *Ty; S.flush(); - return Str.find(Pattern) != std::string::npos; + return isTypeNameOfInterest(Str); } -bool IDETypeStateAnalysis::hasMatchingType(IDETypeStateAnalysis::d_t V) { + +bool IDETypeStateAnalysisBase::hasMatchingType(d_t V) { // General case if (V->getType()->isPointerTy()) { - if (hasMatchingTypeName(V->getType()->getPointerElementType(), - TSD->getTypeNameOfInterest())) { + if (hasMatchingTypeName(V->getType()->getPointerElementType())) { return true; } } if (const auto *Alloca = llvm::dyn_cast(V)) { if (Alloca->getAllocatedType()->isPointerTy()) { if (hasMatchingTypeName( - Alloca->getAllocatedType()->getPointerElementType(), - TSD->getTypeNameOfInterest())) { + Alloca->getAllocatedType()->getPointerElementType())) { return true; } } return false; } if (const auto *Load = llvm::dyn_cast(V)) { - if (Load->getPointerOperand() - ->getType() - ->getPointerElementType() - ->isPointerTy()) { - if (hasMatchingTypeName(Load->getPointerOperand() - ->getType() - ->getPointerElementType() - ->getPointerElementType(), - TSD->getTypeNameOfInterest())) { + if (Load->getType()->isPointerTy()) { + if (hasMatchingTypeName(Load->getType()->getPointerElementType())) { return true; } } @@ -715,8 +334,7 @@ bool IDETypeStateAnalysis::hasMatchingType(IDETypeStateAnalysis::d_t V) { if (const auto *Store = llvm::dyn_cast(V)) { if (Store->getValueOperand()->getType()->isPointerTy()) { if (hasMatchingTypeName( - Store->getValueOperand()->getType()->getPointerElementType(), - TSD->getTypeNameOfInterest())) { + Store->getValueOperand()->getType()->getPointerElementType())) { return true; } } @@ -725,76 +343,4 @@ bool IDETypeStateAnalysis::hasMatchingType(IDETypeStateAnalysis::d_t V) { return false; } -void IDETypeStateAnalysis::emitTextReport( - const SolverResults &SR, - llvm::raw_ostream &OS) { - - LLVMBasedCFG CFG; - OS << "\n======= TYPE STATE RESULTS =======\n"; - for (const auto &F : IRDB->getAllFunctions()) { - OS << '\n' << getFunctionNameFromIR(F) << '\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'; - } - } else { - OS << "\nInst: " << NtoString(&I) << '\n' - << "Fact: " << DtoString(Res.first) << '\n' - << "State: " << LtoString(Res.second) << '\n'; - } - } - } else { - 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' - << "\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"; - } - } else { - OS << "\nInst: " << NtoString(&I) << '\n' - << "Fact: " << DtoString(Res.first) << '\n' - << "State: " << LtoString(Res.second) << '\n'; - } - } - } - } - } - OS << "\n--------------------------------------------\n"; - } -} - -} // namespace psr +} // namespace psr::detail diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp index 13e86dba83..69cd1f1a2b 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp @@ -178,21 +178,6 @@ bool IFDSConstAnalysis::isZeroValue( return LLVMZeroValue::isLLVMZeroValue(Fact); } -void IFDSConstAnalysis::printNode(llvm::raw_ostream &OS, - IFDSConstAnalysis::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IFDSConstAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - IFDSConstAnalysis::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IFDSConstAnalysis::printFunction(llvm::raw_ostream &OS, - IFDSConstAnalysis::f_t Func) const { - OS << Func->getName(); -} - void IFDSConstAnalysis::printInitMemoryLocations() { PHASAR_LOG_LEVEL( DEBUG, "Printing all initialized memory location (or one of its alias)"); diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp index 1f1674dc4f..8b1eb73414 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp @@ -34,6 +34,8 @@ #include #include +#include + namespace psr { IFDSFieldSensTaintAnalysis::IFDSFieldSensTaintAnalysis( @@ -259,3 +261,25 @@ void IFDSFieldSensTaintAnalysis::emitTextReport( } } // namespace psr + +std::string psr::DToString(const ExtendedValue &EV) { + std::string Ret; + llvm::raw_string_ostream OS(Ret); + OS << llvmIRToString(EV.getValue()) << "\n"; + for (const auto *MemLocationPart : EV.getMemLocationSeq()) { + OS << "A:\t" << llvmIRToString(MemLocationPart) << "\n"; + } + if (!EV.getEndOfTaintedBlockLabel().empty()) { + OS << "L:\t" << EV.getEndOfTaintedBlockLabel() << "\n"; + } + if (EV.isVarArg()) { + OS << "VT:\t" << EV.isVarArgTemplate() << "\n"; + for (const auto *VAListMemLocationPart : EV.getVaListMemLocationSeq()) { + OS << "VLA:\t" << llvmIRToString(VAListMemLocationPart) << "\n"; + } + OS << "VI:\t" << EV.getVarArgIndex() << "\n"; + OS << "CI:\t" << EV.getCurrentVarArgIndex() << "\n"; + } + + return Ret; +} diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp index 39e250f791..d35ef58f95 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp @@ -79,19 +79,4 @@ bool IFDSProtoAnalysis::isZeroValue( return LLVMZeroValue::isLLVMZeroValue(Fact); } -void IFDSProtoAnalysis::printNode(llvm::raw_ostream &OS, - IFDSProtoAnalysis::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IFDSProtoAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - IFDSProtoAnalysis::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IFDSProtoAnalysis::printFunction(llvm::raw_ostream &OS, - IFDSProtoAnalysis::f_t Func) const { - OS << Func->getName(); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.cpp index c1de13f385..9ea9e96097 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSignAnalysis.cpp @@ -73,19 +73,4 @@ bool IFDSSignAnalysis::isZeroValue(IFDSSignAnalysis::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } -void IFDSSignAnalysis::printNode(llvm::raw_ostream &OS, - IFDSSignAnalysis::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IFDSSignAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - IFDSSignAnalysis::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IFDSSignAnalysis::printFunction(llvm::raw_ostream &OS, - IFDSSignAnalysis::f_t Func) const { - OS << Func->getName(); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.cpp index b17702224a..6017323011 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSSolverTest.cpp @@ -73,19 +73,4 @@ bool IFDSSolverTest::isZeroValue(IFDSSolverTest::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } -void IFDSSolverTest::printNode(llvm::raw_ostream &OS, - IFDSSolverTest::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IFDSSolverTest::printDataFlowFact(llvm::raw_ostream &OS, - IFDSSolverTest::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IFDSSolverTest::printFunction(llvm::raw_ostream &OS, - IFDSSolverTest::f_t Func) const { - OS << Func->getName(); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp index f49d22c5a6..890c357ad5 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp @@ -359,19 +359,6 @@ bool IFDSTaintAnalysis::isZeroValue(d_t FlowFact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(FlowFact); } -void IFDSTaintAnalysis::printNode(llvm::raw_ostream &Os, n_t Inst) const { - Os << llvmIRToString(Inst); -} - -void IFDSTaintAnalysis::printDataFlowFact(llvm::raw_ostream &Os, - d_t FlowFact) const { - Os << llvmIRToString(FlowFact); -} - -void IFDSTaintAnalysis::printFunction(llvm::raw_ostream &Os, f_t Fun) const { - Os << Fun->getName(); -} - void IFDSTaintAnalysis::emitTextReport( const SolverResults & /*SR*/, llvm::raw_ostream &OS) { diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp index 37eb656605..f7521ff33e 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTypeAnalysis.cpp @@ -98,19 +98,4 @@ bool IFDSTypeAnalysis::isZeroValue(IFDSTypeAnalysis::d_t Fact) const noexcept { return LLVMZeroValue::isLLVMZeroValue(Fact); } -void IFDSTypeAnalysis::printNode(llvm::raw_ostream &OS, - IFDSTypeAnalysis::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IFDSTypeAnalysis::printDataFlowFact(llvm::raw_ostream &OS, - IFDSTypeAnalysis::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IFDSTypeAnalysis::printFunction(llvm::raw_ostream &OS, - IFDSTypeAnalysis::f_t Func) const { - OS << Func->getName(); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp index a527b4332f..7dea9e963b 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.cpp @@ -16,6 +16,7 @@ #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" +#include "phasar/Utils/Printer.h" #include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/Constants.h" @@ -401,21 +402,6 @@ bool IFDSUninitializedVariables::isZeroValue( return LLVMZeroValue::isLLVMZeroValue(Fact); } -void IFDSUninitializedVariables::printNode( - llvm::raw_ostream &OS, IFDSUninitializedVariables::n_t Stmt) const { - OS << llvmIRToString(Stmt); -} - -void IFDSUninitializedVariables::printDataFlowFact( - llvm::raw_ostream &OS, IFDSUninitializedVariables::d_t Fact) const { - OS << llvmIRToShortString(Fact); -} - -void IFDSUninitializedVariables::printFunction( - llvm::raw_ostream &OS, IFDSUninitializedVariables::f_t Func) const { - OS << Func->getName(); -} - void IFDSUninitializedVariables::emitTextReport( const SolverResults & /*Result*/, @@ -435,13 +421,11 @@ void IFDSUninitializedVariables::emitTextReport( for (const auto &User : UndefValueUses) { OS << "\n--------------------------------- " << ++Count << ". Use ---------------------------------\n\n"; - OS << "At IR statement: "; - printNode(OS, User.first); + OS << "At IR statement: " << NToString(User.first); OS << "\n in function: " << getFunctionNameFromIR(User.first); OS << "\n in module : " << getModuleIDFromIR(User.first) << "\n\n"; for (const auto *UndefV : User.second) { - OS << " Uninit Value: "; - printDataFlowFact(OS, UndefV); + OS << " Uninit Value: " << DToString(UndefV); OS << '\n'; } } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp index b6b8895edf..ba640d0bab 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.cpp @@ -9,70 +9,114 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" + +#include "llvm/ADT/StringMap.h" #include "llvm/Support/ErrorHandling.h" +#include + namespace psr { +/** + * We use the following lattice + * BOT = all information + * + * UNINIT OPENED CLOSED ERROR + * + * TOP = no information + */ +// enum class CSTDFILEIOState { +// TOP = 42, +// UNINIT = 0, +// OPENED = 1, +// CLOSED = 2, +// ERROR = 3, +// BOT = 4 +// }; + +namespace { + +/** + * The STAR token represents all API functions besides fopen(), fdopen() and + * fclose(). FOPEN covers fopen() and fdopen() since both functions are + * modeled the same in our case. + */ +enum class CSTDFILEIOToken { FOPEN = 0, FCLOSE = 1, STAR = 2 }; + +constexpr CSTDFILEIOState Delta[3][5] = { + /* FOPEN */ + {CSTDFILEIOState::OPENED, CSTDFILEIOState::OPENED, CSTDFILEIOState::OPENED, + CSTDFILEIOState::ERROR, CSTDFILEIOState::OPENED}, + /* FCLOSE */ + {CSTDFILEIOState::ERROR, CSTDFILEIOState::CLOSED, CSTDFILEIOState::ERROR, + CSTDFILEIOState::ERROR, CSTDFILEIOState::BOT}, + /* STAR */ + {CSTDFILEIOState::ERROR, CSTDFILEIOState::OPENED, CSTDFILEIOState::ERROR, + CSTDFILEIOState::ERROR, CSTDFILEIOState::BOT}, +}; + +const llvm::StringMap> &getStdFileIOFuncs() noexcept { + // Return value is modeled as -1 + static const llvm::StringMap> StdFileIOFuncs = { + {"fopen", {-1}}, {"fdopen", {-1}}, {"fclose", {0}}, + {"fread", {3}}, {"fwrite", {3}}, {"fgetc", {0}}, + {"fgetwc", {0}}, {"fgets", {2}}, {"getc", {0}}, + {"getwc", {0}}, {"_IO_getc", {0}}, {"ungetc", {1}}, + {"ungetwc", {1}}, {"fputc", {1}}, {"fputwc", {1}}, + {"fputs", {1}}, {"putc", {1}}, {"putwc", {1}}, + {"_IO_putc", {1}}, {"fprintf", {0}}, {"fwprintf", {0}}, + {"vfprintf", {0}}, {"vfwprintf", {0}}, {"__isoc99_fscanf", {0}}, + {"fscanf", {0}}, {"fwscanf", {0}}, {"vfscanf", {0}}, + {"vfwscanf", {0}}, {"fflush", {0}}, {"fseek", {0}}, + {"ftell", {0}}, {"rewind", {0}}, {"fgetpos", {0}}, + {"fsetpos", {0}}, {"fileno", {0}}}; + return StdFileIOFuncs; +} + +CSTDFILEIOToken funcNameToToken(llvm::StringRef F) { + if (F == "fopen" || F == "fdopen") { + return CSTDFILEIOToken::FOPEN; + } + if (F == "fclose") { + return CSTDFILEIOToken::FCLOSE; + } + return CSTDFILEIOToken::STAR; +} -// Return value is modeled as -1 -const std::map> - CSTDFILEIOTypeStateDescription::StdFileIOFuncs = { - {"fopen", {-1}}, {"fdopen", {-1}}, {"fclose", {0}}, - {"fread", {3}}, {"fwrite", {3}}, {"fgetc", {0}}, - {"fgetwc", {0}}, {"fgets", {2}}, {"getc", {0}}, - {"getwc", {0}}, {"_IO_getc", {0}}, {"ungetc", {1}}, - {"ungetwc", {1}}, {"fputc", {1}}, {"fputwc", {1}}, - {"fputs", {1}}, {"putc", {1}}, {"putwc", {1}}, - {"_IO_putc", {1}}, {"fprintf", {0}}, {"fwprintf", {0}}, - {"vfprintf", {0}}, {"vfwprintf", {0}}, {"__isoc99_fscanf", {0}}, - {"fscanf", {0}}, {"fwscanf", {0}}, {"vfscanf", {0}}, - {"vfwscanf", {0}}, {"fflush", {0}}, {"fseek", {0}}, - {"ftell", {0}}, {"rewind", {0}}, {"fgetpos", {0}}, - {"fsetpos", {0}}, {"fileno", {0}}}; +} // namespace // delta[Token][State] = next State // Token: FOPEN = 0, FCLOSE = 1, STAR = 2 // States: UNINIT = 0, OPENED = 1, CLOSED = 2, ERROR = 3, BOT = 4 -const CSTDFILEIOTypeStateDescription::CSTDFILEIOState - CSTDFILEIOTypeStateDescription::Delta[3][5] = { - /* FOPEN */ - {CSTDFILEIOState::OPENED, CSTDFILEIOState::OPENED, - CSTDFILEIOState::OPENED, CSTDFILEIOState::ERROR, - CSTDFILEIOState::OPENED}, - /* FCLOSE */ - {CSTDFILEIOState::ERROR, CSTDFILEIOState::CLOSED, - CSTDFILEIOState::ERROR, CSTDFILEIOState::ERROR, CSTDFILEIOState::BOT}, - /* STAR */ - {CSTDFILEIOState::ERROR, CSTDFILEIOState::OPENED, - CSTDFILEIOState::ERROR, CSTDFILEIOState::ERROR, CSTDFILEIOState::BOT}, -}; bool CSTDFILEIOTypeStateDescription::isFactoryFunction( - const std::string &F) const { + llvm::StringRef F) const { if (isAPIFunction(F)) { - return StdFileIOFuncs.at(F).find(-1) != StdFileIOFuncs.at(F).end(); + return getStdFileIOFuncs().lookup(F).count(-1); } return false; } bool CSTDFILEIOTypeStateDescription::isConsumingFunction( - const std::string &F) const { + llvm::StringRef F) const { if (isAPIFunction(F)) { - return StdFileIOFuncs.at(F).find(-1) == StdFileIOFuncs.at(F).end(); + return !getStdFileIOFuncs().lookup(F).count(-1); } return false; } -bool CSTDFILEIOTypeStateDescription::isAPIFunction(const std::string &F) const { - return StdFileIOFuncs.find(F) != StdFileIOFuncs.end(); +bool CSTDFILEIOTypeStateDescription::isAPIFunction(llvm::StringRef F) const { + return getStdFileIOFuncs().count(F); } -TypeStateDescription::State CSTDFILEIOTypeStateDescription::getNextState( - std::string Tok, TypeStateDescription::State S) const { +CSTDFILEIOState +CSTDFILEIOTypeStateDescription::getNextState(llvm::StringRef Tok, + State S) const { if (isAPIFunction(Tok)) { auto X = static_cast>( funcNameToToken(Tok)); - auto Ret = Delta[X][S]; + auto Ret = Delta[X][int(S)]; // if (ret == error()) { // std::cerr << "getNextState(" << Tok << ", " << stateToString(S) // << ") = " << stateToString(Ret) << std::endl; @@ -86,16 +130,16 @@ std::string CSTDFILEIOTypeStateDescription::getTypeNameOfInterest() const { return "struct._IO_FILE"; } -std::set CSTDFILEIOTypeStateDescription::getConsumerParamIdx( - const std::string &F) const { +std::set +CSTDFILEIOTypeStateDescription::getConsumerParamIdx(llvm::StringRef F) const { if (isConsumingFunction(F)) { - return StdFileIOFuncs.at(F); + return getStdFileIOFuncs().lookup(F); } return {}; } std::set -CSTDFILEIOTypeStateDescription::getFactoryParamIdx(const std::string &F) const { +CSTDFILEIOTypeStateDescription::getFactoryParamIdx(llvm::StringRef F) const { if (isFactoryFunction(F)) { // Trivial here, since we only generate via return value return {-1}; @@ -103,9 +147,8 @@ CSTDFILEIOTypeStateDescription::getFactoryParamIdx(const std::string &F) const { return {}; } -std::string CSTDFILEIOTypeStateDescription::stateToString( - TypeStateDescription::State S) const { - switch (S) { +llvm::StringRef to_string(CSTDFILEIOState State) noexcept { + switch (State) { case CSTDFILEIOState::TOP: return "TOP"; break; @@ -124,41 +167,31 @@ std::string CSTDFILEIOTypeStateDescription::stateToString( case CSTDFILEIOState::BOT: return "BOT"; break; - default: - llvm::report_fatal_error("received unknown state!"); - break; } + + llvm::report_fatal_error("received unknown state!"); } -TypeStateDescription::State CSTDFILEIOTypeStateDescription::bottom() const { +CSTDFILEIOState CSTDFILEIOTypeStateDescription::bottom() const { return CSTDFILEIOState::BOT; } -TypeStateDescription::State CSTDFILEIOTypeStateDescription::top() const { +CSTDFILEIOState CSTDFILEIOTypeStateDescription::top() const { return CSTDFILEIOState::TOP; } -TypeStateDescription::State CSTDFILEIOTypeStateDescription::uninit() const { +CSTDFILEIOState CSTDFILEIOTypeStateDescription::uninit() const { return CSTDFILEIOState::UNINIT; } -TypeStateDescription::State CSTDFILEIOTypeStateDescription::start() const { +CSTDFILEIOState CSTDFILEIOTypeStateDescription::start() const { return CSTDFILEIOState::OPENED; } -TypeStateDescription::State CSTDFILEIOTypeStateDescription::error() const { +CSTDFILEIOState CSTDFILEIOTypeStateDescription::error() const { return CSTDFILEIOState::ERROR; } -CSTDFILEIOTypeStateDescription::CSTDFILEIOToken -CSTDFILEIOTypeStateDescription::funcNameToToken(const std::string &F) { - if (F == "fopen" || F == "fdopen") { - return CSTDFILEIOToken::FOPEN; - } - if (F == "fclose") { - return CSTDFILEIOToken::FCLOSE; - } - return CSTDFILEIOToken::STAR; -} +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 ec29574024..df37f0bcb6 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.cpp @@ -21,12 +21,11 @@ namespace psr { // Return value is modeled as -1 -const std::map> - OpenSSLEVPKDFCTXDescription::OpenSSLEVPKDFFuncs = { - {"EVP_KDF_CTX_new", {-1}}, - {"EVP_KDF_CTX_set_params", {0}}, - {"EVP_KDF_derive", {0}}, - {"EVP_KDF_CTX_free", {0}} +static const std::map> OpenSSLEVPKDFFuncs = { + {"EVP_KDF_CTX_new", {-1}}, + {"EVP_KDF_CTX_set_params", {0}}, + {"EVP_KDF_derive", {0}}, + {"EVP_KDF_CTX_free", {0}} }; @@ -39,86 +38,82 @@ const std::map> // // States: UNINIT = 5, CTX_ATTACHED =1, PARAM_INIT = 2, // DERIVED = 3, ERROR = 4, BOT = 0 -const OpenSSLEVPKDFCTXDescription::OpenSSLEVPKDFState - OpenSSLEVPKDFCTXDescription::Delta[5][6] = { - - /* EVP_KDF_CTX_NEW */ - {OpenSSLEVPKDFState::CTX_ATTACHED, OpenSSLEVPKDFState::CTX_ATTACHED, - OpenSSLEVPKDFState::CTX_ATTACHED, OpenSSLEVPKDFState::CTX_ATTACHED, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::CTX_ATTACHED}, - /* EVP_KDF_CTX_SET_PARAMS */ - {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::PARAM_INIT, - OpenSSLEVPKDFState::PARAM_INIT, OpenSSLEVPKDFState::PARAM_INIT, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::ERROR}, - /* DERIVE */ - {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::ERROR, - OpenSSLEVPKDFState::DERIVED, OpenSSLEVPKDFState::DERIVED, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::ERROR}, - /* EVP_KDF_CTX_FREE */ - {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::UNINIT, - OpenSSLEVPKDFState::UNINIT, OpenSSLEVPKDFState::UNINIT, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::ERROR}, - - /* STAR */ - {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::CTX_ATTACHED, - OpenSSLEVPKDFState::PARAM_INIT, OpenSSLEVPKDFState::DERIVED, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::ERROR}, +const OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::Delta[5][6] = { + + /* EVP_KDF_CTX_NEW */ + {OpenSSLEVPKDFCTXState::CTX_ATTACHED, OpenSSLEVPKDFCTXState::CTX_ATTACHED, + OpenSSLEVPKDFCTXState::CTX_ATTACHED, OpenSSLEVPKDFCTXState::CTX_ATTACHED, + OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + /* EVP_KDF_CTX_SET_PARAMS */ + {OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::PARAM_INIT, + OpenSSLEVPKDFCTXState::PARAM_INIT, OpenSSLEVPKDFCTXState::PARAM_INIT, + OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::ERROR}, + /* DERIVE */ + {OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::ERROR, + OpenSSLEVPKDFCTXState::DERIVED, OpenSSLEVPKDFCTXState::DERIVED, + OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::ERROR}, + /* EVP_KDF_CTX_FREE */ + {OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::UNINIT, + OpenSSLEVPKDFCTXState::UNINIT, OpenSSLEVPKDFCTXState::UNINIT, + OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::ERROR}, + + /* STAR */ + {OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::CTX_ATTACHED, + OpenSSLEVPKDFCTXState::PARAM_INIT, OpenSSLEVPKDFCTXState::DERIVED, + OpenSSLEVPKDFCTXState::ERROR, OpenSSLEVPKDFCTXState::ERROR}, }; -bool OpenSSLEVPKDFCTXDescription::isFactoryFunction( - const std::string &F) const { +bool OpenSSLEVPKDFCTXDescription::isFactoryFunction(llvm::StringRef F) const { if (isAPIFunction(F)) { return OpenSSLEVPKDFFuncs.at(F).find(-1) != OpenSSLEVPKDFFuncs.at(F).end(); } return false; } -bool OpenSSLEVPKDFCTXDescription::isConsumingFunction( - const std::string &F) const { +bool OpenSSLEVPKDFCTXDescription::isConsumingFunction(llvm::StringRef F) const { if (isAPIFunction(F)) { return OpenSSLEVPKDFFuncs.at(F).find(-1) == OpenSSLEVPKDFFuncs.at(F).end(); } return false; } -bool OpenSSLEVPKDFCTXDescription::isAPIFunction(const std::string &F) const { +bool OpenSSLEVPKDFCTXDescription::isAPIFunction(llvm::StringRef F) const { return OpenSSLEVPKDFFuncs.find(F) != OpenSSLEVPKDFFuncs.end(); } -TypeStateDescription::State -OpenSSLEVPKDFCTXDescription::getNextState(std::string Tok, +OpenSSLEVPKDFCTXState +OpenSSLEVPKDFCTXDescription::getNextState(llvm::StringRef Tok, TypeStateDescription::State S) const { if (isAPIFunction(Tok)) { auto NameToTok = funcNameToToken(Tok); auto Ret = Delta[static_cast>( - NameToTok)][S]; + NameToTok)][int(S)]; // std::cout << "delta[" << Tok << ", " << stateToString(S) // << "] = " << stateToString(ret) << std::endl; return Ret; } - return OpenSSLEVPKDFState::BOT; + return OpenSSLEVPKDFCTXState::BOT; } -TypeStateDescription::State OpenSSLEVPKDFCTXDescription::getNextState( - const std::string &Tok, TypeStateDescription::State S, +OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::getNextState( + llvm::StringRef Tok, TypeStateDescription::State S, const llvm::CallBase *CallSite) const { if (isAPIFunction(Tok)) { auto NameToTok = funcNameToToken(Tok); auto Ret = Delta[static_cast>( - NameToTok)][S]; + NameToTok)][int(S)]; if (NameToTok == OpenSSLEVTKDFToken::EVP_KDF_CTX_NEW) { // require the kdf here to be in KDF_FETCHED state // requiredKDFState[make_pair(CS.getInstruction(), CS.getArgOperand(0))] = - // (OpenSSLEVPKDFDescription::OpenSSLEVPKDFState::KDF_FETCHED); + // (OpenSSLEVPKDFDescription::OpenSSLEVPKDFCTXState::KDF_FETCHED); // cout << "## Factory-Call: "; // cout.flush(); // cout << llvmIRToShortString(CS.getInstruction()) << endl; auto KdfState = KDFAnalysisResults.resultAt(CallSite, CallSite->getArgOperand(0)); - if (KdfState != - OpenSSLEVPKDFDescription::OpenSSLEVPKDFState::KDF_FETCHED) { + if (KdfState != OpenSSLEVPKDFState::KDF_FETCHED) { return error(); } } @@ -126,7 +121,7 @@ TypeStateDescription::State OpenSSLEVPKDFCTXDescription::getNextState( // << "] = " << stateToString(ret) << std::endl; return Ret; } - return OpenSSLEVPKDFState::BOT; + return OpenSSLEVPKDFCTXState::BOT; } std::string OpenSSLEVPKDFCTXDescription::getTypeNameOfInterest() const { @@ -134,7 +129,7 @@ std::string OpenSSLEVPKDFCTXDescription::getTypeNameOfInterest() const { } std::set -OpenSSLEVPKDFCTXDescription::getConsumerParamIdx(const std::string &F) const { +OpenSSLEVPKDFCTXDescription::getConsumerParamIdx(llvm::StringRef F) const { if (isConsumingFunction(F)) { return OpenSSLEVPKDFFuncs.at(F); } @@ -142,7 +137,7 @@ OpenSSLEVPKDFCTXDescription::getConsumerParamIdx(const std::string &F) const { } std::set -OpenSSLEVPKDFCTXDescription::getFactoryParamIdx(const std::string &F) const { +OpenSSLEVPKDFCTXDescription::getFactoryParamIdx(llvm::StringRef F) const { if (isFactoryFunction(F)) { // Trivial here, since we only generate via return value return {-1}; @@ -150,59 +145,57 @@ OpenSSLEVPKDFCTXDescription::getFactoryParamIdx(const std::string &F) const { return {}; } -std::string OpenSSLEVPKDFCTXDescription::stateToString( - TypeStateDescription::State S) const { - switch (S) { - case OpenSSLEVPKDFState::TOP: +llvm::StringRef to_string(OpenSSLEVPKDFCTXState State) noexcept { + switch (State) { + case OpenSSLEVPKDFCTXState::TOP: return "TOP"; break; - case OpenSSLEVPKDFState::UNINIT: + case OpenSSLEVPKDFCTXState::UNINIT: return "UNINIT"; break; - case OpenSSLEVPKDFState::CTX_ATTACHED: + case OpenSSLEVPKDFCTXState::CTX_ATTACHED: return "CTX_ATTACHED"; break; - case OpenSSLEVPKDFState::PARAM_INIT: + case OpenSSLEVPKDFCTXState::PARAM_INIT: return "PARAM_INIT"; break; - case OpenSSLEVPKDFState::DERIVED: + case OpenSSLEVPKDFCTXState::DERIVED: return "DERIVED"; break; - case OpenSSLEVPKDFState::ERROR: + case OpenSSLEVPKDFCTXState::ERROR: return "ERROR"; break; - case OpenSSLEVPKDFState::BOT: + case OpenSSLEVPKDFCTXState::BOT: return "BOT"; break; - default: - llvm::report_fatal_error("received unknown state!"); - break; } + + llvm::report_fatal_error("received unknown state!"); } -TypeStateDescription::State OpenSSLEVPKDFCTXDescription::bottom() const { - return OpenSSLEVPKDFState::BOT; +OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::bottom() const { + return OpenSSLEVPKDFCTXState::BOT; } -TypeStateDescription::State OpenSSLEVPKDFCTXDescription::top() const { - return OpenSSLEVPKDFState::TOP; +OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::top() const { + return OpenSSLEVPKDFCTXState::TOP; } -TypeStateDescription::State OpenSSLEVPKDFCTXDescription::uninit() const { - return OpenSSLEVPKDFState::UNINIT; +OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::uninit() const { + return OpenSSLEVPKDFCTXState::UNINIT; } -TypeStateDescription::State OpenSSLEVPKDFCTXDescription::start() const { - return OpenSSLEVPKDFState::CTX_ATTACHED; +OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::start() const { + return OpenSSLEVPKDFCTXState::CTX_ATTACHED; } -TypeStateDescription::State OpenSSLEVPKDFCTXDescription::error() const { - return OpenSSLEVPKDFState::ERROR; +OpenSSLEVPKDFCTXState OpenSSLEVPKDFCTXDescription::error() const { + return OpenSSLEVPKDFCTXState::ERROR; } OpenSSLEVPKDFCTXDescription::OpenSSLEVTKDFToken -OpenSSLEVPKDFCTXDescription::funcNameToToken(const std::string &F) { +OpenSSLEVPKDFCTXDescription::funcNameToToken(llvm::StringRef F) { if (F == "EVP_KDF_CTX_new") { return OpenSSLEVTKDFToken::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 89068b96f5..4c0973cf7e 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.cpp @@ -9,6 +9,8 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/TypeStateDescription.h" + #include "llvm/Support/ErrorHandling.h" #include @@ -16,9 +18,8 @@ namespace psr { // Return value is modeled as -1 -const std::map> - OpenSSLEVPKDFDescription::OpenSSLEVPKDFFuncs = {{"EVP_KDF_fetch", {-1}}, - {"EVP_KDF_free", {0}} +static const std::map> OpenSSLEVPKDFFuncs = { + {"EVP_KDF_fetch", {-1}}, {"EVP_KDF_free", {0}} }; @@ -28,44 +29,43 @@ const std::map> // STAR = 2 // // States: UNINIT = 0, KDF_FETCHED = 1, ERROR = 2, BOT = 3 -const OpenSSLEVPKDFDescription::OpenSSLEVPKDFState - OpenSSLEVPKDFDescription::Delta[3][4] = { - /* EVP_KDF_FETCH */ - {OpenSSLEVPKDFState::KDF_FETCHED, OpenSSLEVPKDFState::ERROR, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::KDF_FETCHED}, - /* EVP_KDF_CTX_FREE */ - {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::UNINIT, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::BOT}, - - /* STAR */ - {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::KDF_FETCHED, - OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::BOT}, +const OpenSSLEVPKDFState OpenSSLEVPKDFDescription::Delta[3][4] = { + /* EVP_KDF_FETCH */ + {OpenSSLEVPKDFState::KDF_FETCHED, OpenSSLEVPKDFState::ERROR, + OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::KDF_FETCHED}, + /* EVP_KDF_CTX_FREE */ + {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::UNINIT, + OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::BOT}, + + /* STAR */ + {OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::KDF_FETCHED, + OpenSSLEVPKDFState::ERROR, OpenSSLEVPKDFState::BOT}, }; -bool OpenSSLEVPKDFDescription::isFactoryFunction(const std::string &F) const { +bool OpenSSLEVPKDFDescription::isFactoryFunction(llvm::StringRef F) const { if (isAPIFunction(F)) { return OpenSSLEVPKDFFuncs.at(F).find(-1) != OpenSSLEVPKDFFuncs.at(F).end(); } return false; } -bool OpenSSLEVPKDFDescription::isConsumingFunction(const std::string &F) const { +bool OpenSSLEVPKDFDescription::isConsumingFunction(llvm::StringRef F) const { if (isAPIFunction(F)) { return OpenSSLEVPKDFFuncs.at(F).find(-1) == OpenSSLEVPKDFFuncs.at(F).end(); } return false; } -bool OpenSSLEVPKDFDescription::isAPIFunction(const std::string &F) const { +bool OpenSSLEVPKDFDescription::isAPIFunction(llvm::StringRef F) const { return OpenSSLEVPKDFFuncs.find(F) != OpenSSLEVPKDFFuncs.end(); } -TypeStateDescription::State -OpenSSLEVPKDFDescription::getNextState(std::string Tok, +OpenSSLEVPKDFState +OpenSSLEVPKDFDescription::getNextState(llvm::StringRef Tok, TypeStateDescription::State S) const { if (isAPIFunction(Tok)) { auto Ret = Delta[static_cast>( - funcNameToToken(Tok))][S]; + funcNameToToken(Tok))][int(S)]; // std::cout << "Delta[" << Tok << ", " << stateToString(S) // << "] = " << stateToString(ret) << std::endl; return Ret; @@ -78,7 +78,7 @@ std::string OpenSSLEVPKDFDescription::getTypeNameOfInterest() const { } std::set -OpenSSLEVPKDFDescription::getConsumerParamIdx(const std::string &F) const { +OpenSSLEVPKDFDescription::getConsumerParamIdx(llvm::StringRef F) const { if (isConsumingFunction(F)) { return OpenSSLEVPKDFFuncs.at(F); } @@ -86,7 +86,7 @@ OpenSSLEVPKDFDescription::getConsumerParamIdx(const std::string &F) const { } std::set -OpenSSLEVPKDFDescription::getFactoryParamIdx(const std::string &F) const { +OpenSSLEVPKDFDescription::getFactoryParamIdx(llvm::StringRef F) const { if (isFactoryFunction(F)) { // Trivial here, since we only generate via return value return {-1}; @@ -94,9 +94,8 @@ OpenSSLEVPKDFDescription::getFactoryParamIdx(const std::string &F) const { return {}; } -std::string -OpenSSLEVPKDFDescription::stateToString(TypeStateDescription::State S) const { - switch (S) { +llvm::StringRef to_string(OpenSSLEVPKDFState State) noexcept { + switch (State) { case OpenSSLEVPKDFState::TOP: return "TOP"; case OpenSSLEVPKDFState::UNINIT: @@ -107,34 +106,32 @@ OpenSSLEVPKDFDescription::stateToString(TypeStateDescription::State S) const { return "ERROR"; case OpenSSLEVPKDFState::BOT: return "BOT"; - default: - llvm::report_fatal_error("received unknown state!"); - break; } + llvm::report_fatal_error("received unknown state!"); } -TypeStateDescription::State OpenSSLEVPKDFDescription::bottom() const { +OpenSSLEVPKDFState OpenSSLEVPKDFDescription::bottom() const { return OpenSSLEVPKDFState::BOT; } -TypeStateDescription::State OpenSSLEVPKDFDescription::top() const { +OpenSSLEVPKDFState OpenSSLEVPKDFDescription::top() const { return OpenSSLEVPKDFState::TOP; } -TypeStateDescription::State OpenSSLEVPKDFDescription::uninit() const { +OpenSSLEVPKDFState OpenSSLEVPKDFDescription::uninit() const { return OpenSSLEVPKDFState::UNINIT; } -TypeStateDescription::State OpenSSLEVPKDFDescription::start() const { +OpenSSLEVPKDFState OpenSSLEVPKDFDescription::start() const { return OpenSSLEVPKDFState::KDF_FETCHED; } -TypeStateDescription::State OpenSSLEVPKDFDescription::error() const { +OpenSSLEVPKDFState OpenSSLEVPKDFDescription::error() const { return OpenSSLEVPKDFState::ERROR; } OpenSSLEVPKDFDescription::OpenSSLEVTKDFToken -OpenSSLEVPKDFDescription::funcNameToToken(const std::string &FuncName) { +OpenSSLEVPKDFDescription::funcNameToToken(llvm::StringRef FuncName) { if (FuncName == "EVP_KDF_fetch") { return OpenSSLEVTKDFToken::EVP_KDF_FETCH; } diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp index b0cc0cc870..3c0a90a67f 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.cpp @@ -18,48 +18,45 @@ using namespace psr; namespace psr { // Return value is modeled as -1 -const std::map> - OpenSSLSecureHeapDescription::OpenSSLSecureHeapFuncs = { - {"CRYPTO_secure_malloc", {-1}}, - {"CRYPTO_secure_zalloc", {-1}}, - {"CRYPTO_secure_free", {0}}, - {"CRYPTO_secure_clear_free", {0}}}; +static const std::map> OpenSSLSecureHeapFuncs = { + {"CRYPTO_secure_malloc", {-1}}, + {"CRYPTO_secure_zalloc", {-1}}, + {"CRYPTO_secure_free", {0}}, + {"CRYPTO_secure_clear_free", {0}}}; // delta[Token][State] = next State // Token: SECURE_MALLOC = 0, SECURE_ZALLOC = 1, SECURE_FREE = 2, // SECURE_CLEAR_FREE = 3, STAR = 4 // // States: BOT = 0, UNINIT = 1, ALLOCATED = 2, ZEROED = 3, FREED = 4, ERROR = 5 -const OpenSSLSecureHeapDescription::OpenSSLSecureHeapState - OpenSSLSecureHeapDescription::Delta[5][6] = { - // SECURE_MALLOC - {OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ALLOCATED, - OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ALLOCATED, - OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ALLOCATED}, - // SECURE_ZALLOC - {OpenSSLSecureHeapState::ZEROED, OpenSSLSecureHeapState::ZEROED, - OpenSSLSecureHeapState::ZEROED, OpenSSLSecureHeapState::ZEROED, - OpenSSLSecureHeapState::ZEROED, OpenSSLSecureHeapState::ZEROED}, - // SECURE_FREE - {OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR, - OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::FREED, - OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR}, - // SECURE_CLEAR_FREE - {OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR, - OpenSSLSecureHeapState::FREED, OpenSSLSecureHeapState::FREED, - OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR}, - // STAR - {OpenSSLSecureHeapState::BOT, OpenSSLSecureHeapState::UNINIT, - OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ZEROED, - OpenSSLSecureHeapState::FREED, OpenSSLSecureHeapState::ERROR}, +const OpenSSLSecureHeapState OpenSSLSecureHeapDescription::Delta[5][6] = { + // SECURE_MALLOC + {OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ALLOCATED, + OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ALLOCATED, + OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ALLOCATED}, + // SECURE_ZALLOC + {OpenSSLSecureHeapState::ZEROED, OpenSSLSecureHeapState::ZEROED, + OpenSSLSecureHeapState::ZEROED, OpenSSLSecureHeapState::ZEROED, + OpenSSLSecureHeapState::ZEROED, OpenSSLSecureHeapState::ZEROED}, + // SECURE_FREE + {OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR, + OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::FREED, + OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR}, + // SECURE_CLEAR_FREE + {OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR, + OpenSSLSecureHeapState::FREED, OpenSSLSecureHeapState::FREED, + OpenSSLSecureHeapState::ERROR, OpenSSLSecureHeapState::ERROR}, + // STAR + {OpenSSLSecureHeapState::BOT, OpenSSLSecureHeapState::UNINIT, + OpenSSLSecureHeapState::ALLOCATED, OpenSSLSecureHeapState::ZEROED, + OpenSSLSecureHeapState::FREED, OpenSSLSecureHeapState::ERROR}, }; OpenSSLSecureHeapDescription::OpenSSLSecureHeapDescription( IDESolver &SecureHeapPropagationResults) : SecureHeapPropagationResults(SecureHeapPropagationResults) {} -bool OpenSSLSecureHeapDescription::isFactoryFunction( - const std::string &F) const { +bool OpenSSLSecureHeapDescription::isFactoryFunction(llvm::StringRef F) const { if (isAPIFunction(F)) { return OpenSSLSecureHeapFuncs.at(F).find(-1) != OpenSSLSecureHeapFuncs.at(F).end(); @@ -68,7 +65,7 @@ bool OpenSSLSecureHeapDescription::isFactoryFunction( } bool OpenSSLSecureHeapDescription::isConsumingFunction( - const std::string &F) const { + llvm::StringRef F) const { if (isAPIFunction(F)) { return OpenSSLSecureHeapFuncs.at(F).find(-1) == OpenSSLSecureHeapFuncs.at(F).end(); @@ -76,23 +73,23 @@ bool OpenSSLSecureHeapDescription::isConsumingFunction( return false; } -bool OpenSSLSecureHeapDescription::isAPIFunction(const std::string &F) const { +bool OpenSSLSecureHeapDescription::isAPIFunction(llvm::StringRef F) const { return OpenSSLSecureHeapFuncs.find(F) != OpenSSLSecureHeapFuncs.end(); } -TypeStateDescription::State OpenSSLSecureHeapDescription::getNextState( - std::string Tok, TypeStateDescription::State S) const { +OpenSSLSecureHeapState OpenSSLSecureHeapDescription::getNextState( + llvm::StringRef Tok, TypeStateDescription::State S) const { if (isAPIFunction(Tok)) { auto Ftok = static_cast>( funcNameToToken(Tok)); - return Delta[Ftok][S]; + return Delta[Ftok][int(S)]; } return OpenSSLSecureHeapState::BOT; } -TypeStateDescription::State OpenSSLSecureHeapDescription::getNextState( - const std::string &Tok, TypeStateDescription::State S, +OpenSSLSecureHeapState OpenSSLSecureHeapDescription::getNextState( + llvm::StringRef Tok, TypeStateDescription::State S, const llvm::CallBase *CallSite) const { if (isAPIFunction(Tok)) { auto Ftok = static_cast>( @@ -104,7 +101,7 @@ TypeStateDescription::State OpenSSLSecureHeapDescription::getNextState( // << llvmIRToShortString(CS.getInstruction()) << std::endl; return error(); } - return Delta[Ftok][S]; + return Delta[Ftok][int(S)]; } return error(); } @@ -114,7 +111,7 @@ std::string OpenSSLSecureHeapDescription::getTypeNameOfInterest() const { } set -OpenSSLSecureHeapDescription::getConsumerParamIdx(const std::string &F) const { +OpenSSLSecureHeapDescription::getConsumerParamIdx(llvm::StringRef F) const { if (isConsumingFunction(F)) { return OpenSSLSecureHeapFuncs.at(F); } @@ -122,7 +119,7 @@ OpenSSLSecureHeapDescription::getConsumerParamIdx(const std::string &F) const { } set -OpenSSLSecureHeapDescription::getFactoryParamIdx(const std::string &F) const { +OpenSSLSecureHeapDescription::getFactoryParamIdx(llvm::StringRef F) const { if (isFactoryFunction(F)) { // Trivial here, since we only generate via return value return {-1}; @@ -130,9 +127,8 @@ OpenSSLSecureHeapDescription::getFactoryParamIdx(const std::string &F) const { return {}; } -std::string OpenSSLSecureHeapDescription::stateToString( - TypeStateDescription::State S) const { - switch (S) { +llvm::StringRef to_string(OpenSSLSecureHeapState State) noexcept { + switch (State) { case OpenSSLSecureHeapState::TOP: return "TOP"; case OpenSSLSecureHeapState::BOT: @@ -145,35 +141,35 @@ std::string OpenSSLSecureHeapDescription::stateToString( return "FREED"; case OpenSSLSecureHeapState::ERROR: return "ERROR"; - default: - llvm::report_fatal_error("received unknown state!"); - break; + case OpenSSLSecureHeapState::ZEROED: + return "ZEROED"; } + llvm::report_fatal_error("received unknown state!"); } -TypeStateDescription::State OpenSSLSecureHeapDescription::bottom() const { +OpenSSLSecureHeapState OpenSSLSecureHeapDescription::bottom() const { return OpenSSLSecureHeapState::BOT; } -TypeStateDescription::State OpenSSLSecureHeapDescription::top() const { +OpenSSLSecureHeapState OpenSSLSecureHeapDescription::top() const { return OpenSSLSecureHeapState::TOP; } -TypeStateDescription::State OpenSSLSecureHeapDescription::start() const { +OpenSSLSecureHeapState OpenSSLSecureHeapDescription::start() const { llvm::report_fatal_error("TypeStateDescription::start() is deprecated"); return OpenSSLSecureHeapState::BOT; } -TypeStateDescription::State OpenSSLSecureHeapDescription::uninit() const { +OpenSSLSecureHeapState OpenSSLSecureHeapDescription::uninit() const { return OpenSSLSecureHeapState::UNINIT; } -TypeStateDescription::State OpenSSLSecureHeapDescription::error() const { +OpenSSLSecureHeapState OpenSSLSecureHeapDescription::error() const { return OpenSSLSecureHeapState::ERROR; } OpenSSLSecureHeapDescription::OpenSSLSecureHeapToken -OpenSSLSecureHeapDescription::funcNameToToken(const std::string &F) { +OpenSSLSecureHeapDescription::funcNameToToken(llvm::StringRef F) { return llvm::StringSwitch(F) .Case("CRYPTO_secure_malloc", OpenSSLSecureHeapToken::SECURE_MALLOC) .Case("CRYPTO_secure_zalloc", OpenSSLSecureHeapToken::SECURE_ZALLOC) diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp index f5b383ef2a..e71e30b0ea 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.cpp @@ -13,75 +13,99 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include + +#include + using namespace std; using namespace psr; namespace psr { - -// Return value is modeled as -1 -const std::map> - OpenSSLSecureMemoryDescription::OpenSSLSecureMemoryFuncs = { - {"CRYPTO_malloc", {-1}}, - {"CRYPTO_zalloc", {-1}}, - {"OPENSSL_cleanse", {0}}, - {"CRYPTO_free", {0}}}; +enum class OpenSSLSecureMemoryState { + TOP = 42, + BOT = 0, + ZEROED = 1, + FREED = 2, + ERROR = 3, + ALLOCATED = 4 +}; + +namespace { + +enum class OpenSSLSecureMemoryToken { + CRYPTO_MALLOC = 0, + CRYPTO_ZALLOC = 1, + CRYPTO_FREE = 2, + OPENSSL_CLEANSE = 3, + STAR = 4 +}; + +constexpr std::array FactoryFuncs = {"CRYPTO_malloc", + "CRYPTO_zalloc"}; +constexpr std::array, 2> ConsumingFuncs = { + {{"CRYPTO_free", 0}, {"OPENSSL_cleanse", 0}}, +}; // delta[Token][State] = next State // Token: CRYPTO_MALLOC=0, CRYPTO_ZALLOC=1, CRYPTO_FREE=2, OPENSSL_CLEANSE=3, // STAR = 4 // // States: ALLOCATED=4, ZEROED=1, FREED=2, ERROR=3, BOT=0 -const OpenSSLSecureMemoryDescription::OpenSSLSecureMemoryState - OpenSSLSecureMemoryDescription::Delta[6][7] = { - // CRYPTO_malloc - {OpenSSLSecureMemoryState::ALLOCATED, - OpenSSLSecureMemoryState::ALLOCATED, - OpenSSLSecureMemoryState::ALLOCATED, OpenSSLSecureMemoryState::ERROR, - OpenSSLSecureMemoryState::ALLOCATED}, - // CRYPTO_ZALLOC - {OpenSSLSecureMemoryState::ZEROED, OpenSSLSecureMemoryState::ZEROED, - OpenSSLSecureMemoryState::ZEROED, OpenSSLSecureMemoryState::ERROR, - OpenSSLSecureMemoryState::ZEROED}, - // CRYPTO_FREE - {OpenSSLSecureMemoryState::ERROR, OpenSSLSecureMemoryState::FREED, - OpenSSLSecureMemoryState::ERROR, OpenSSLSecureMemoryState::ERROR, - OpenSSLSecureMemoryState::ERROR}, - // OPENSSL_CLEANSE - {OpenSSLSecureMemoryState::BOT, OpenSSLSecureMemoryState::ZEROED, - OpenSSLSecureMemoryState::ERROR, OpenSSLSecureMemoryState::ERROR, - OpenSSLSecureMemoryState::ZEROED}, - // STAR (kills ZEROED) - {OpenSSLSecureMemoryState::BOT, OpenSSLSecureMemoryState::ALLOCATED, - OpenSSLSecureMemoryState::FREED, OpenSSLSecureMemoryState::ERROR, - OpenSSLSecureMemoryState::ALLOCATED}}; +constexpr OpenSSLSecureMemoryState Delta[6][7] = { + // CRYPTO_malloc + {OpenSSLSecureMemoryState::ALLOCATED, OpenSSLSecureMemoryState::ALLOCATED, + OpenSSLSecureMemoryState::ALLOCATED, OpenSSLSecureMemoryState::ERROR, + OpenSSLSecureMemoryState::ALLOCATED}, + // CRYPTO_ZALLOC + {OpenSSLSecureMemoryState::ZEROED, OpenSSLSecureMemoryState::ZEROED, + OpenSSLSecureMemoryState::ZEROED, OpenSSLSecureMemoryState::ERROR, + OpenSSLSecureMemoryState::ZEROED}, + // CRYPTO_FREE + {OpenSSLSecureMemoryState::ERROR, OpenSSLSecureMemoryState::FREED, + OpenSSLSecureMemoryState::ERROR, OpenSSLSecureMemoryState::ERROR, + OpenSSLSecureMemoryState::ERROR}, + // OPENSSL_CLEANSE + {OpenSSLSecureMemoryState::BOT, OpenSSLSecureMemoryState::ZEROED, + OpenSSLSecureMemoryState::ERROR, OpenSSLSecureMemoryState::ERROR, + OpenSSLSecureMemoryState::ZEROED}, + // STAR (kills ZEROED) + {OpenSSLSecureMemoryState::BOT, OpenSSLSecureMemoryState::ALLOCATED, + OpenSSLSecureMemoryState::FREED, OpenSSLSecureMemoryState::ERROR, + OpenSSLSecureMemoryState::ALLOCATED}}; + +OpenSSLSecureMemoryToken funcNameToToken(llvm::StringRef F) { + return llvm::StringSwitch(F) + .Case("CRYPTO_malloc", OpenSSLSecureMemoryToken::CRYPTO_MALLOC) + .Case("CRYPTO_zalloc", OpenSSLSecureMemoryToken::CRYPTO_ZALLOC) + .Case("CRYPTO_free", OpenSSLSecureMemoryToken::CRYPTO_FREE) + .Case("OPENSSL_cleanse", OpenSSLSecureMemoryToken::OPENSSL_CLEANSE) + .Default(OpenSSLSecureMemoryToken::STAR); +} + +} // namespace bool OpenSSLSecureMemoryDescription::isFactoryFunction( - const std::string &F) const { - if (isAPIFunction(F)) { - return OpenSSLSecureMemoryFuncs.at(F).find(-1) != - OpenSSLSecureMemoryFuncs.at(F).end(); - } - return false; + llvm::StringRef F) const { + return llvm::is_contained(FactoryFuncs, F); } bool OpenSSLSecureMemoryDescription::isConsumingFunction( - const std::string &F) const { - if (isAPIFunction(F)) { - return OpenSSLSecureMemoryFuncs.at(F).find(-1) == - OpenSSLSecureMemoryFuncs.at(F).end(); - } - return false; + llvm::StringRef F) const { + return llvm::find_if(ConsumingFuncs, [&F](const auto &Pair) { + return F == Pair.first; + }) != ConsumingFuncs.end(); } -bool OpenSSLSecureMemoryDescription::isAPIFunction(const std::string &F) const { - return OpenSSLSecureMemoryFuncs.find(F) != OpenSSLSecureMemoryFuncs.end(); +bool OpenSSLSecureMemoryDescription::isAPIFunction(llvm::StringRef F) const { + return funcNameToToken(F) != OpenSSLSecureMemoryToken::STAR; } -TypeStateDescription::State OpenSSLSecureMemoryDescription::getNextState( - std::string Tok, TypeStateDescription::State S) const { - if (isAPIFunction(Tok)) { +OpenSSLSecureMemoryState OpenSSLSecureMemoryDescription::getNextState( + llvm::StringRef Tok, TypeStateDescription::State S) const { + auto Token = funcNameToToken(Tok); + if (Token != OpenSSLSecureMemoryToken::STAR) { return Delta[static_cast>( - funcNameToToken(Tok))][S]; + Token)][int(S)]; } return OpenSSLSecureMemoryState::BOT; } @@ -90,16 +114,18 @@ std::string OpenSSLSecureMemoryDescription::getTypeNameOfInterest() const { return "i8"; // NOT SURE WHAT TO DO WITH THIS } -set OpenSSLSecureMemoryDescription::getConsumerParamIdx( - const std::string &F) const { - if (isConsumingFunction(F)) { - return OpenSSLSecureMemoryFuncs.at(F); +set +OpenSSLSecureMemoryDescription::getConsumerParamIdx(llvm::StringRef F) const { + if (const auto *It = llvm::find_if( + ConsumingFuncs, [&F](const auto &Pair) { return F == Pair.first; }); + It != ConsumingFuncs.end()) { + return {It->second}; } return {}; } set -OpenSSLSecureMemoryDescription::getFactoryParamIdx(const std::string &F) const { +OpenSSLSecureMemoryDescription::getFactoryParamIdx(llvm::StringRef F) const { if (isFactoryFunction(F)) { // Trivial here, since we only generate via return value return {-1}; @@ -107,9 +133,8 @@ OpenSSLSecureMemoryDescription::getFactoryParamIdx(const std::string &F) const { return {}; } -std::string OpenSSLSecureMemoryDescription::stateToString( - TypeStateDescription::State S) const { - switch (S) { +llvm::StringRef to_string(OpenSSLSecureMemoryState State) noexcept { + switch (State) { case OpenSSLSecureMemoryState::TOP: return "TOP"; case OpenSSLSecureMemoryState::BOT: @@ -122,40 +147,28 @@ std::string OpenSSLSecureMemoryDescription::stateToString( return "ZEROED"; case OpenSSLSecureMemoryState::ERROR: return "ERROR"; - default: - llvm::report_fatal_error("received unknown state!"); - break; } + llvm::report_fatal_error("received unknown state!"); } -TypeStateDescription::State OpenSSLSecureMemoryDescription::bottom() const { +OpenSSLSecureMemoryState OpenSSLSecureMemoryDescription::bottom() const { return OpenSSLSecureMemoryState::BOT; } -TypeStateDescription::State OpenSSLSecureMemoryDescription::top() const { +OpenSSLSecureMemoryState OpenSSLSecureMemoryDescription::top() const { return OpenSSLSecureMemoryState::TOP; } -TypeStateDescription::State OpenSSLSecureMemoryDescription::start() const { +OpenSSLSecureMemoryState OpenSSLSecureMemoryDescription::start() const { return OpenSSLSecureMemoryState::ALLOCATED; } -TypeStateDescription::State OpenSSLSecureMemoryDescription::uninit() const { +OpenSSLSecureMemoryState OpenSSLSecureMemoryDescription::uninit() const { return OpenSSLSecureMemoryState::BOT; } -TypeStateDescription::State OpenSSLSecureMemoryDescription::error() const { +OpenSSLSecureMemoryState OpenSSLSecureMemoryDescription::error() const { return OpenSSLSecureMemoryState::ERROR; } -OpenSSLSecureMemoryDescription::OpenSSLSecureMemoryToken -OpenSSLSecureMemoryDescription::funcNameToToken(const std::string &F) { - return llvm::StringSwitch(F) - .Case("CRYPTO_malloc", OpenSSLSecureMemoryToken::CRYPTO_MALLOC) - .Case("CRYPTO_zalloc", OpenSSLSecureMemoryToken::CRYPTO_ZALLOC) - .Case("CRYPTO_free", OpenSSLSecureMemoryToken::CRYPTO_FREE) - .Case("OPENSSL_cleanse", OpenSSLSecureMemoryToken::OPENSSL_CLEANSE) - .Default(OpenSSLSecureMemoryToken::STAR); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.cpp b/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.cpp index ec4ce482bd..ca19e4c6f6 100644 --- a/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.cpp +++ b/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.cpp @@ -154,21 +154,6 @@ InterMonoFullConstantPropagation::callToRetFlow( return In; } -void InterMonoFullConstantPropagation::printNode( - llvm::raw_ostream &OS, InterMonoFullConstantPropagation::n_t Inst) const { - IntraMonoFullConstantPropagation::printNode(OS, Inst); -} - -void InterMonoFullConstantPropagation::printDataFlowFact( - llvm::raw_ostream &OS, InterMonoFullConstantPropagation::d_t Fact) const { - IntraMonoFullConstantPropagation::printDataFlowFact(OS, Fact); -} - -void InterMonoFullConstantPropagation::printFunction( - llvm::raw_ostream &OS, InterMonoFullConstantPropagation::f_t Fun) const { - IntraMonoFullConstantPropagation::printFunction(OS, Fun); -} - void InterMonoFullConstantPropagation::printContainer( llvm::raw_ostream &OS, InterMonoFullConstantPropagation::mono_container_t Con) const { diff --git a/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.cpp b/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.cpp index c86df25930..5d14d7fa48 100644 --- a/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.cpp +++ b/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.cpp @@ -102,19 +102,4 @@ InterMonoSolverTest::initialSeeds() { return Seeds; } -void InterMonoSolverTest::printNode(llvm::raw_ostream &OS, - InterMonoSolverTest::n_t Inst) const { - OS << llvmIRToString(Inst); -} - -void InterMonoSolverTest::printDataFlowFact( - llvm::raw_ostream &OS, InterMonoSolverTest::d_t Fact) const { - OS << llvmIRToString(Fact) << '\n'; -} - -void InterMonoSolverTest::printFunction(llvm::raw_ostream &OS, - InterMonoSolverTest::f_t Fun) const { - OS << Fun->getName(); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.cpp b/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.cpp index 4a9e48a995..04830d72ca 100644 --- a/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.cpp @@ -181,20 +181,6 @@ InterMonoTaintAnalysis::initialSeeds() { return Seeds; } -void InterMonoTaintAnalysis::printNode(llvm::raw_ostream &OS, - InterMonoTaintAnalysis::n_t Inst) const { - OS << llvmIRToString(Inst); -} - -void InterMonoTaintAnalysis::printDataFlowFact( - llvm::raw_ostream &OS, InterMonoTaintAnalysis::d_t Fact) const { - OS << llvmIRToString(Fact) << '\n'; -} - -void InterMonoTaintAnalysis::printFunction(llvm::raw_ostream &OS, - const llvm::Function *Fun) const { - OS << Fun->getName(); -} const std::map> & InterMonoTaintAnalysis::getAllLeaks() const { diff --git a/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.cpp b/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.cpp index 4c223bcd7b..2c415cd174 100644 --- a/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.cpp +++ b/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Value.h" +#include "llvm/Support/raw_ostream.h" #include #include @@ -222,30 +223,11 @@ IntraMonoFullConstantPropagation::executeBinOperation( return Res; } -void IntraMonoFullConstantPropagation::printNode( - llvm::raw_ostream &OS, IntraMonoFullConstantPropagation::n_t Inst) const { - OS << llvmIRToString(Inst); -} - -void IntraMonoFullConstantPropagation::printDataFlowFact( - llvm::raw_ostream &OS, IntraMonoFullConstantPropagation::d_t Fact) const { - OS << "< " + llvmIRToString(Fact.first) << ", "; - if (std::holds_alternative(Fact.second)) { - OS << std::get(Fact.second); - } - if (std::holds_alternative(Fact.second)) { - OS << std::get(Fact.second); - } - if (std::holds_alternative( - Fact.second)) { - OS << std::get(Fact.second); - } - OS << " >\n"; -} +} // namespace psr -void IntraMonoFullConstantPropagation::printFunction( - llvm::raw_ostream &OS, IntraMonoFullConstantPropagation::f_t Fun) const { - OS << Fun->getName(); +std::string psr::DToString(const IntraMonoFCAFact &Fact) { + std::string Ret; + llvm::raw_string_ostream OS(Ret); + OS << "< " << llvmIRToString(Fact.Fact) << ", " << Fact.Value << " >\n"; + return Ret; } - -} // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.cpp b/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.cpp index 5becbc3c6c..dc0a9782d5 100644 --- a/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.cpp +++ b/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.cpp @@ -73,19 +73,4 @@ IntraMonoSolverTest::initialSeeds() { return {}; } -void IntraMonoSolverTest::printNode(llvm::raw_ostream &OS, - IntraMonoSolverTest::n_t Inst) const { - OS << llvmIRToString(Inst); -} - -void IntraMonoSolverTest::printDataFlowFact( - llvm::raw_ostream &OS, IntraMonoSolverTest::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IntraMonoSolverTest::printFunction(llvm::raw_ostream &OS, - IntraMonoSolverTest::f_t Fun) const { - OS << Fun->getName(); -} - } // namespace psr diff --git a/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.cpp b/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.cpp index 892cf558d3..3d7aa3a8ac 100644 --- a/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.cpp +++ b/lib/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.cpp @@ -90,19 +90,4 @@ IntraMonoUninitVariables::initialSeeds() { return Seeds; } -void IntraMonoUninitVariables::printNode( - llvm::raw_ostream &OS, IntraMonoUninitVariables::n_t Inst) const { - OS << llvmIRToString(Inst); -} - -void IntraMonoUninitVariables::printDataFlowFact( - llvm::raw_ostream &OS, IntraMonoUninitVariables::d_t Fact) const { - OS << llvmIRToString(Fact); -} - -void IntraMonoUninitVariables::printFunction( - llvm::raw_ostream &OS, IntraMonoUninitVariables::f_t Fun) const { - OS << Fun->getName(); -} - } // namespace psr diff --git a/lib/PhasarLLVM/Utils/LLVMPrinter.cpp b/lib/PhasarLLVM/Utils/LLVMPrinter.cpp new file mode 100644 index 0000000000..23910b444d --- /dev/null +++ b/lib/PhasarLLVM/Utils/LLVMPrinter.cpp @@ -0,0 +1,14 @@ +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/Printer.h" + +#include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" + +std::string psr::NToString(const llvm::Value *V) { return llvmIRToString(V); } +std::string psr::NToString(const llvm::Instruction *V) { + return llvmIRToString(V); +} + +std::string psr::DToString(const llvm::Value *V) { return llvmIRToString(V); } + +llvm::StringRef psr::FToString(const llvm::Function *V) { return V->getName(); } diff --git a/tools/example-tool/myphasartool.cpp b/tools/example-tool/myphasartool.cpp index 642c6fd975..f95f34ce2d 100644 --- a/tools/example-tool/myphasartool.cpp +++ b/tools/example-tool/myphasartool.cpp @@ -42,14 +42,14 @@ int main(int Argc, const char **Argv) { auto L = createAnalysisProblem(HA, EntryPoints); IFDSSolver S(L, &HA.getICFG()); auto IFDSResults = S.solve(); - IFDSResults.dumpResults(HA.getICFG(), L); + IFDSResults.dumpResults(HA.getICFG()); // IDE template parametrization test llvm::outs() << "Testing IDE:\n"; auto M = createAnalysisProblem(HA, EntryPoints); // Alternative way of solving an IFDS/IDEProblem: auto IDEResults = solveIDEProblem(M, HA.getICFG()); - IDEResults.dumpResults(HA.getICFG(), M); + IDEResults.dumpResults(HA.getICFG()); } else { llvm::errs() << "error: file does not contain a 'main' function!\n"; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index a8bf83d155..0b2d4fa52e 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -37,7 +37,7 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { std::optional HA; CSTDFILEIOTypeStateDescription CSTDFILEIODesc{}; - std::optional TSProblem; + std::optional> TSProblem; enum IOSTATE { TOP = 42, UNINIT = 0, @@ -53,7 +53,8 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { void initialize(const llvm::Twine &IRFile) { HA.emplace(IRFile, EntryPoints); - TSProblem = createAnalysisProblem( + TSProblem = createAnalysisProblem< + IDETypeStateAnalysis>( *HA, &CSTDFILEIODesc, EntryPoints); } @@ -69,7 +70,8 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { */ void compareResults( const std::map> &GroundTruth, - IDESolver_P &Solver) { + IDESolver_P> + &Solver) { for (const auto &InstToGroundTruth : GroundTruth) { const auto *Inst = HA->getProjectIRDB().getInstruction(InstToGroundTruth.first); @@ -80,7 +82,7 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { for (auto Result : Solver.resultsAt(Inst, true)) { if (GT.find(getMetaDataID(Result.first)) != GT.end()) { Results.insert(std::pair( - getMetaDataID(Result.first), Result.second)); + getMetaDataID(Result.first), int(Result.second))); } } EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(Inst); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp index c02802f96e..bc74fadfda 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp @@ -20,6 +20,7 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "TestConfig.h" #include "gtest/gtest.h" #include @@ -30,44 +31,51 @@ using namespace psr; /* ============== TEST FIXTURE ============== */ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { protected: - const std::string PathToLlFiles = - PhasarConfig::PhasarDirectory() + - "build/test/llvm_test_code/openssl/key_derivation/"; + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SUBFOLDER("openssl/key_derivation/"); const std::vector EntryPoints = {"main"}; std::optional HA; std::optional OpenSSLEVPKeyDerivationDesc; OpenSSLEVPKDFDescription OpenSSLEVPKDFDesc{}; - std::optional TSProblem, TSKDFProblem; - unique_ptr> Llvmtssolver, KdfSolver; - - enum OpenSSLEVPKeyDerivationState { - TOP = 42, - UNINIT = 5, - CTX_ATTACHED = 1, - PARAM_INIT = 2, - DERIVED = 3, - ERROR = 4, - BOT = 0 - }; + std::optional> TSProblem; + std::optional> TSKDFProblem; + unique_ptr>> + Llvmtssolver; + unique_ptr>> + KdfSolver; + + // enum OpenSSLEVPKDFCTXState { + // TOP = 42, + // UNINIT = 5, + // CTX_ATTACHED = 1, + // PARAM_INIT = 2, + // DERIVED = 3, + // ERROR = 4, + // BOT = 0 + // }; IDETSAnalysisOpenSSLEVPKDFTest() = default; ~IDETSAnalysisOpenSSLEVPKDFTest() override = default; - void initialize(const std::string &IRFile) { - HA.emplace(IRFile, EntryPoints); + void initialize(const llvm::Twine &IRFile) { + HA.emplace(PathToLlFiles + IRFile, EntryPoints); - TSKDFProblem = createAnalysisProblem( - *HA, &OpenSSLEVPKDFDesc, EntryPoints); + TSKDFProblem = + createAnalysisProblem>( + *HA, &OpenSSLEVPKDFDesc, EntryPoints); - KdfSolver = make_unique>( + KdfSolver = make_unique< + IDESolver>>( *TSKDFProblem, &HA->getICFG()); OpenSSLEVPKeyDerivationDesc.emplace(*KdfSolver); - TSProblem = createAnalysisProblem( + TSProblem = createAnalysisProblem< + IDETypeStateAnalysis>( *HA, &*OpenSSLEVPKeyDerivationDesc, EntryPoints); - Llvmtssolver = make_unique>( + Llvmtssolver = make_unique< + IDESolver>>( *TSProblem, &HA->getICFG()); KdfSolver->solve(); Llvmtssolver->solve(); @@ -85,16 +93,17 @@ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { * @param solver provides the results */ void compareResults( - const std::map> &GroundTruth) { + const std::map> + &GroundTruth) { for (const auto &InstToGroundTruth : GroundTruth) { const auto *Inst = HA->getProjectIRDB().getInstruction(InstToGroundTruth.first); auto GT = InstToGroundTruth.second; - std::map Results; + std::map Results; for (auto Result : Llvmtssolver->resultsAt(Inst, true)) { - if (Result.second != OpenSSLEVPKeyDerivationState::BOT && + if (Result.second != OpenSSLEVPKDFCTXState::BOT && GT.count(getMetaDataID(Result.first))) { - Results.insert(std::pair( + Results.insert(std::pair( getMetaDataID(Result.first), Result.second)); } } @@ -104,234 +113,234 @@ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { }; // Test Fixture TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, KeyDerivation1) { - initialize({PathToLlFiles + "key-derivation1_c.ll"}); + initialize("key-derivation1_c.ll"); // llvmtssolver->printReport(); - std::map> Gt; - - Gt[48] = {{"46", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"20", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[50] = {{"46", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"20", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - - Gt[92] = {{"46", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"20", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"88", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[98] = {{"95", OpenSSLEVPKeyDerivationState::DERIVED}, - {"46", OpenSSLEVPKeyDerivationState::DERIVED}, - {"20", OpenSSLEVPKeyDerivationState::DERIVED}, - {"88", OpenSSLEVPKeyDerivationState::DERIVED}}; - Gt[146] = {{"144", OpenSSLEVPKeyDerivationState::UNINIT}, - {"95", OpenSSLEVPKeyDerivationState::UNINIT}, - {"46", OpenSSLEVPKeyDerivationState::UNINIT}, - {"20", OpenSSLEVPKeyDerivationState::UNINIT}, - {"88", OpenSSLEVPKeyDerivationState::UNINIT}}; + std::map> Gt; + + Gt[48] = {{"46", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"20", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[50] = {{"46", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"20", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + + Gt[92] = {{"46", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"20", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"88", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[98] = {{"95", OpenSSLEVPKDFCTXState::DERIVED}, + {"46", OpenSSLEVPKDFCTXState::DERIVED}, + {"20", OpenSSLEVPKDFCTXState::DERIVED}, + {"88", OpenSSLEVPKDFCTXState::DERIVED}}; + Gt[146] = {{"144", OpenSSLEVPKDFCTXState::UNINIT}, + {"95", OpenSSLEVPKDFCTXState::UNINIT}, + {"46", OpenSSLEVPKDFCTXState::UNINIT}, + {"20", OpenSSLEVPKDFCTXState::UNINIT}, + {"88", OpenSSLEVPKDFCTXState::UNINIT}}; compareResults(Gt); } TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, KeyDerivation2) { - initialize({PathToLlFiles + "key-derivation2_c.ll"}); + initialize("key-derivation2_c.ll"); - std::map> Gt; - // gt[40] = {{"22", OpenSSLEVPKeyDerivationState::UNINIT}}; // killed by + std::map> Gt; + // gt[40] = {{"22", OpenSSLEVPKDFCTXState::UNINIT}}; // killed by // null-initialization - // gt[57] = {{"22", OpenSSLEVPKeyDerivationState::UNINIT}}; // killed by + // gt[57] = {{"22", OpenSSLEVPKDFCTXState::UNINIT}}; // killed by // null-initialization - Gt[60] = {{"22", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"58", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[105] = {{"22", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"58", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"103", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[106] = {{"22", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"58", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"103", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[112] = {{"22", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"58", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"103", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"110", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[113] = {{"22", OpenSSLEVPKeyDerivationState::DERIVED}, - {"58", OpenSSLEVPKeyDerivationState::DERIVED}, - {"103", OpenSSLEVPKeyDerivationState::DERIVED}, - {"110", OpenSSLEVPKeyDerivationState::DERIVED}}; - Gt[160] = {{"22", OpenSSLEVPKeyDerivationState::DERIVED}, - {"58", OpenSSLEVPKeyDerivationState::DERIVED}, - {"103", OpenSSLEVPKeyDerivationState::DERIVED}, - {"110", OpenSSLEVPKeyDerivationState::DERIVED}, - {"159", OpenSSLEVPKeyDerivationState::DERIVED}}; - Gt[161] = {{"22", OpenSSLEVPKeyDerivationState::UNINIT}, - {"58", OpenSSLEVPKeyDerivationState::UNINIT}, - {"103", OpenSSLEVPKeyDerivationState::UNINIT}, - {"110", OpenSSLEVPKeyDerivationState::UNINIT}, - {"159", OpenSSLEVPKeyDerivationState::UNINIT}}; + Gt[60] = {{"22", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"58", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[105] = {{"22", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"58", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"103", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[106] = {{"22", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"58", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"103", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[112] = {{"22", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"58", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"103", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"110", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[113] = {{"22", OpenSSLEVPKDFCTXState::DERIVED}, + {"58", OpenSSLEVPKDFCTXState::DERIVED}, + {"103", OpenSSLEVPKDFCTXState::DERIVED}, + {"110", OpenSSLEVPKDFCTXState::DERIVED}}; + Gt[160] = {{"22", OpenSSLEVPKDFCTXState::DERIVED}, + {"58", OpenSSLEVPKDFCTXState::DERIVED}, + {"103", OpenSSLEVPKDFCTXState::DERIVED}, + {"110", OpenSSLEVPKDFCTXState::DERIVED}, + {"159", OpenSSLEVPKDFCTXState::DERIVED}}; + Gt[161] = {{"22", OpenSSLEVPKDFCTXState::UNINIT}, + {"58", OpenSSLEVPKDFCTXState::UNINIT}, + {"103", OpenSSLEVPKDFCTXState::UNINIT}, + {"110", OpenSSLEVPKDFCTXState::UNINIT}, + {"159", OpenSSLEVPKDFCTXState::UNINIT}}; // Fails due to merge conflicts: ID43 and ID162 have both value UNINIT on 22, // but it is implicit at ID43, so merging gives BOT - // gt[164] = {{"22", OpenSSLEVPKeyDerivationState::UNINIT}}; + // gt[164] = {{"22", OpenSSLEVPKDFCTXState::UNINIT}}; compareResults(Gt); } TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, KeyDerivation3) { - initialize({PathToLlFiles + "key-derivation3_c.ll"}); - std::map> Gt; + initialize("key-derivation3_c.ll"); + std::map> Gt; - // gt[56] = {{"21", OpenSSLEVPKeyDerivationState::UNINIT}}; // + // gt[56] = {{"21", OpenSSLEVPKDFCTXState::UNINIT}}; // // null-initialization kills 21 - Gt[58] = {{"56", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"21", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[93] = {{"56", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"21", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"91", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[94] = {{"56", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"21", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"91", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[100] = {{"56", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"21", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"91", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"98", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[101] = {{"56", OpenSSLEVPKeyDerivationState::DERIVED}, - {"21", OpenSSLEVPKeyDerivationState::DERIVED}, - {"91", OpenSSLEVPKeyDerivationState::DERIVED}, - {"98", OpenSSLEVPKeyDerivationState::DERIVED}}; - Gt[148] = {{"56", OpenSSLEVPKeyDerivationState::DERIVED}, - {"21", OpenSSLEVPKeyDerivationState::DERIVED}, - {"91", OpenSSLEVPKeyDerivationState::DERIVED}, - {"98", OpenSSLEVPKeyDerivationState::DERIVED}, - {"147", OpenSSLEVPKeyDerivationState::DERIVED}}; - Gt[149] = {{"56", OpenSSLEVPKeyDerivationState::UNINIT}, - {"21", OpenSSLEVPKeyDerivationState::UNINIT}, - {"91", OpenSSLEVPKeyDerivationState::UNINIT}, - {"98", OpenSSLEVPKeyDerivationState::UNINIT}, - {"147", OpenSSLEVPKeyDerivationState::UNINIT}}; + Gt[58] = {{"56", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"21", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[93] = {{"56", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"21", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"91", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[94] = {{"56", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"21", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"91", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[100] = {{"56", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"21", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"91", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"98", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[101] = {{"56", OpenSSLEVPKDFCTXState::DERIVED}, + {"21", OpenSSLEVPKDFCTXState::DERIVED}, + {"91", OpenSSLEVPKDFCTXState::DERIVED}, + {"98", OpenSSLEVPKDFCTXState::DERIVED}}; + Gt[148] = {{"56", OpenSSLEVPKDFCTXState::DERIVED}, + {"21", OpenSSLEVPKDFCTXState::DERIVED}, + {"91", OpenSSLEVPKDFCTXState::DERIVED}, + {"98", OpenSSLEVPKDFCTXState::DERIVED}, + {"147", OpenSSLEVPKDFCTXState::DERIVED}}; + Gt[149] = {{"56", OpenSSLEVPKDFCTXState::UNINIT}, + {"21", OpenSSLEVPKDFCTXState::UNINIT}, + {"91", OpenSSLEVPKDFCTXState::UNINIT}, + {"98", OpenSSLEVPKDFCTXState::UNINIT}, + {"147", OpenSSLEVPKDFCTXState::UNINIT}}; compareResults(Gt); } TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, KeyDerivation4) { - initialize({PathToLlFiles + "key-derivation4_c.ll"}); + initialize("key-derivation4_c.ll"); - std::map> Gt; + std::map> Gt; - // gt[57] = {{"21", OpenSSLEVPKeyDerivationState::UNINIT}}; // + // gt[57] = {{"21", OpenSSLEVPKDFCTXState::UNINIT}}; // // null-initialization kills 21 - Gt[59] = {{"21", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"57", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[104] = {{"21", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"57", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"102", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[105] = {{"21", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"57", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"102", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; + Gt[59] = {{"21", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"57", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[104] = {{"21", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"57", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"102", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[105] = {{"21", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"57", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"102", OpenSSLEVPKDFCTXState::PARAM_INIT}}; // TODO: Should FREE on PARAM_INIT result in UNINIT, or in ERROR? (currently // it is UNINIT) - Gt[152] = {{"21", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"57", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"102", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"151", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[153] = {{"21", OpenSSLEVPKeyDerivationState::UNINIT}, - {"57", OpenSSLEVPKeyDerivationState::UNINIT}, - {"102", OpenSSLEVPKeyDerivationState::UNINIT}, - {"151", OpenSSLEVPKeyDerivationState::UNINIT}}; + Gt[152] = {{"21", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"57", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"102", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"151", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[153] = {{"21", OpenSSLEVPKDFCTXState::UNINIT}, + {"57", OpenSSLEVPKDFCTXState::UNINIT}, + {"102", OpenSSLEVPKDFCTXState::UNINIT}, + {"151", OpenSSLEVPKDFCTXState::UNINIT}}; compareResults(Gt); } TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, KeyDerivation5) { - initialize({PathToLlFiles + "key-derivation5_c.ll"}); + initialize("key-derivation5_c.ll"); - std::map> Gt; + std::map> Gt; - // gt[58] = {{"22", OpenSSLEVPKeyDerivationState::UNINIT}};// + // gt[58] = {{"22", OpenSSLEVPKDFCTXState::UNINIT}};// // null-initialization kills 22 - Gt[60] = {{"22", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"58", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[105] = {{"22", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"58", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"103", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[106] = {{"22", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"58", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"103", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[112] = {{"22", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"58", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"103", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"110", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[113] = Gt[160] = {{"22", OpenSSLEVPKeyDerivationState::DERIVED}, - {"58", OpenSSLEVPKeyDerivationState::DERIVED}, - {"103", OpenSSLEVPKeyDerivationState::DERIVED}, - {"110", OpenSSLEVPKeyDerivationState::DERIVED}}; + Gt[60] = {{"22", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"58", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[105] = {{"22", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"58", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"103", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[106] = {{"22", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"58", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"103", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[112] = {{"22", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"58", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"103", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"110", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[113] = Gt[160] = {{"22", OpenSSLEVPKDFCTXState::DERIVED}, + {"58", OpenSSLEVPKDFCTXState::DERIVED}, + {"103", OpenSSLEVPKDFCTXState::DERIVED}, + {"110", OpenSSLEVPKDFCTXState::DERIVED}}; // should report an error at 160? (kdf_ctx is not freed) compareResults(Gt); } TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, DISABLED_KeyDerivation6) { - initialize({PathToLlFiles + "key-derivation6_c.ll"}); + initialize("key-derivation6_c.ll"); // llvmtssolver->printReport(); - std::map> Gt; - Gt[102] = {{"100", OpenSSLEVPKeyDerivationState::BOT}, - {"22", OpenSSLEVPKeyDerivationState::BOT}}; - Gt[103] = {{"100", OpenSSLEVPKeyDerivationState::ERROR}, - {"22", OpenSSLEVPKeyDerivationState::ERROR}}; - Gt[109] = Gt[110] = {{"100", OpenSSLEVPKeyDerivationState::ERROR}, - {"22", OpenSSLEVPKeyDerivationState::ERROR}, - {"107", OpenSSLEVPKeyDerivationState::ERROR}}; + std::map> Gt; + Gt[102] = {{"100", OpenSSLEVPKDFCTXState::BOT}, + {"22", OpenSSLEVPKDFCTXState::BOT}}; + Gt[103] = {{"100", OpenSSLEVPKDFCTXState::ERROR}, + {"22", OpenSSLEVPKDFCTXState::ERROR}}; + Gt[109] = Gt[110] = {{"100", OpenSSLEVPKDFCTXState::ERROR}, + {"22", OpenSSLEVPKDFCTXState::ERROR}, + {"107", OpenSSLEVPKDFCTXState::ERROR}}; compareResults(Gt); } TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, KeyDerivation7) { - initialize({PathToLlFiles + "key-derivation7_c.ll"}); + initialize("key-derivation7_c.ll"); // llvmtssolver->printReport(); - std::map> Gt; + std::map> Gt; - // gt[57] = {{"21", OpenSSLEVPKeyDerivationState::UNINIT}}; // + // gt[57] = {{"21", OpenSSLEVPKDFCTXState::UNINIT}}; // // null-initialization kills 21 - Gt[59] = {{"21", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"57", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[104] = {{"21", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"57", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"102", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[105] = {{"21", OpenSSLEVPKeyDerivationState::ERROR}, - {"57", OpenSSLEVPKeyDerivationState::ERROR}, - {"102", OpenSSLEVPKeyDerivationState::ERROR}}; - Gt[152] = Gt[153] = {{"21", OpenSSLEVPKeyDerivationState::ERROR}, - {"57", OpenSSLEVPKeyDerivationState::ERROR}, - {"102", OpenSSLEVPKeyDerivationState::ERROR}, - {"151", OpenSSLEVPKeyDerivationState::ERROR}}; + Gt[59] = {{"21", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"57", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[104] = {{"21", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"57", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"102", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[105] = {{"21", OpenSSLEVPKDFCTXState::ERROR}, + {"57", OpenSSLEVPKDFCTXState::ERROR}, + {"102", OpenSSLEVPKDFCTXState::ERROR}}; + Gt[152] = Gt[153] = {{"21", OpenSSLEVPKDFCTXState::ERROR}, + {"57", OpenSSLEVPKDFCTXState::ERROR}, + {"102", OpenSSLEVPKDFCTXState::ERROR}, + {"151", OpenSSLEVPKDFCTXState::ERROR}}; compareResults(Gt); } TEST_F(IDETSAnalysisOpenSSLEVPKDFTest, KeyDerivation8) { - initialize({PathToLlFiles + "key-derivation8_c.ll"}); + initialize("key-derivation8_c.ll"); // llvmtssolver->printReport(); - std::map> Gt; + std::map> Gt; - // gt[58] = {{"22", OpenSSLEVPKeyDerivationState::UNINIT}}; // + // gt[58] = {{"22", OpenSSLEVPKDFCTXState::UNINIT}}; // // null-initialization kills 22 - Gt[60] = {{"22", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"58", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[105] = {{"22", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"58", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}, - {"103", OpenSSLEVPKeyDerivationState::CTX_ATTACHED}}; - Gt[107] = {{"22", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"58", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"103", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[112] = {{"22", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"58", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"103", OpenSSLEVPKeyDerivationState::PARAM_INIT}, - {"110", OpenSSLEVPKeyDerivationState::PARAM_INIT}}; - Gt[113] = {{"22", OpenSSLEVPKeyDerivationState::DERIVED}, - {"58", OpenSSLEVPKeyDerivationState::DERIVED}, - {"103", OpenSSLEVPKeyDerivationState::DERIVED}, - {"110", OpenSSLEVPKeyDerivationState::DERIVED}}; - Gt[160] = {{"22", OpenSSLEVPKeyDerivationState::DERIVED}, - {"58", OpenSSLEVPKeyDerivationState::DERIVED}, - {"103", OpenSSLEVPKeyDerivationState::DERIVED}, - {"110", OpenSSLEVPKeyDerivationState::DERIVED}, - {"159", OpenSSLEVPKeyDerivationState::DERIVED}}; - Gt[161] = {{"22", OpenSSLEVPKeyDerivationState::UNINIT}, - {"58", OpenSSLEVPKeyDerivationState::UNINIT}, - {"103", OpenSSLEVPKeyDerivationState::UNINIT}, - {"110", OpenSSLEVPKeyDerivationState::UNINIT}, - {"159", OpenSSLEVPKeyDerivationState::UNINIT}}; + Gt[60] = {{"22", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"58", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[105] = {{"22", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"58", OpenSSLEVPKDFCTXState::CTX_ATTACHED}, + {"103", OpenSSLEVPKDFCTXState::CTX_ATTACHED}}; + Gt[107] = {{"22", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"58", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"103", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[112] = {{"22", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"58", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"103", OpenSSLEVPKDFCTXState::PARAM_INIT}, + {"110", OpenSSLEVPKDFCTXState::PARAM_INIT}}; + Gt[113] = {{"22", OpenSSLEVPKDFCTXState::DERIVED}, + {"58", OpenSSLEVPKDFCTXState::DERIVED}, + {"103", OpenSSLEVPKDFCTXState::DERIVED}, + {"110", OpenSSLEVPKDFCTXState::DERIVED}}; + Gt[160] = {{"22", OpenSSLEVPKDFCTXState::DERIVED}, + {"58", OpenSSLEVPKDFCTXState::DERIVED}, + {"103", OpenSSLEVPKDFCTXState::DERIVED}, + {"110", OpenSSLEVPKDFCTXState::DERIVED}, + {"159", OpenSSLEVPKDFCTXState::DERIVED}}; + Gt[161] = {{"22", OpenSSLEVPKDFCTXState::UNINIT}, + {"58", OpenSSLEVPKDFCTXState::UNINIT}, + {"103", OpenSSLEVPKDFCTXState::UNINIT}, + {"110", OpenSSLEVPKDFCTXState::UNINIT}, + {"159", OpenSSLEVPKDFCTXState::UNINIT}}; compareResults(Gt); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp index 4546dc44c8..a4cc5eb869 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/Twine.h" +#include "TestConfig.h" #include "gtest/gtest.h" #include @@ -33,17 +34,18 @@ using namespace psr; /* ============== TEST FIXTURE ============== */ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { protected: - const std::string PathToLlFiles = - PhasarConfig::PhasarDirectory() + - "build/test/llvm_test_code/openssl/secure_heap/"; + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SUBFOLDER("openssl/secure_heap/"); const std::vector EntryPoints = {"main"}; std::optional HA; std::optional Desc; - std::optional TSProblem; + std::optional> TSProblem; std::optional SecureHeapPropagationProblem; - unique_ptr> Llvmtssolver; + unique_ptr< + IDESolver>> + Llvmtssolver; unique_ptr> SecureHeapPropagationResults; enum OpenSSLSecureHeapState { @@ -58,7 +60,7 @@ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { IDETSAnalysisOpenSSLSecureHeapTest() = default; ~IDETSAnalysisOpenSSLSecureHeapTest() override = default; - void initialize(const std::string &IRFile) { + void initialize(const llvm::Twine &IRFile) { HA.emplace(IRFile, EntryPoints); SecureHeapPropagationProblem = @@ -68,9 +70,11 @@ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { *SecureHeapPropagationProblem, &HA->getICFG()); Desc.emplace(*SecureHeapPropagationResults); - TSProblem = - createAnalysisProblem(*HA, &*Desc, EntryPoints); - Llvmtssolver = make_unique>( + TSProblem = createAnalysisProblem< + IDETypeStateAnalysis>(*HA, &*Desc, + EntryPoints); + Llvmtssolver = make_unique< + IDESolver>>( *TSProblem, &HA->getICFG()); SecureHeapPropagationResults->solve(); @@ -97,7 +101,7 @@ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { for (auto Result : Llvmtssolver->resultsAt(Inst, true)) { if (GT.find(getMetaDataID(Result.first)) != GT.end()) { Results.insert(std::pair( - getMetaDataID(Result.first), Result.second)); + getMetaDataID(Result.first), int(Result.second))); } // else { // std::cout << "Unused result at " << InstToGroundTruth.first << ": " // << llvmIRToShortString(Result.first) << " => " diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp index 3006943b71..558c8007c4 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp @@ -19,6 +19,7 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "TestConfig.h" #include "gtest/gtest.h" #include @@ -30,15 +31,15 @@ using namespace psr; /* ============== TEST FIXTURE ============== */ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { protected: - const std::string PathToLlFiles = - PhasarConfig::PhasarDirectory() + - "build/test/llvm_test_code/openssl/secure_memory/"; + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SUBFOLDER("openssl/secure_memory/"); const std::vector EntryPoints = {"main"}; std::optional HA; OpenSSLSecureMemoryDescription Desc{}; - std::optional TSProblem; - unique_ptr> Llvmtssolver; + std::optional> TSProblem; + unique_ptr>> + Llvmtssolver; enum OpenSSLSecureMemoryState { TOP = 42, @@ -51,12 +52,14 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { IDETSAnalysisOpenSSLSecureMemoryTest() = default; ~IDETSAnalysisOpenSSLSecureMemoryTest() override = default; - void initialize(const std::string &IRFile) { + void initialize(const llvm::Twine &&IRFile) { HA.emplace(IRFile, EntryPoints); - TSProblem = - createAnalysisProblem(*HA, &Desc, EntryPoints); - Llvmtssolver = make_unique>( + TSProblem = createAnalysisProblem< + IDETypeStateAnalysis>(*HA, &Desc, + EntryPoints); + Llvmtssolver = make_unique< + IDESolver_P>>( *TSProblem, &HA->getICFG()); Llvmtssolver->solve(); @@ -82,7 +85,7 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { for (auto Result : Llvmtssolver->resultsAt(Inst, true)) { if (GT.find(getMetaDataID(Result.first)) != GT.end()) { Results.insert(std::pair( - getMetaDataID(Result.first), Result.second)); + getMetaDataID(Result.first), int(Result.second))); } // else { // std::cout << "Unused result at " << InstToGroundTruth.first << ": " // << llvmIRToShortString(Result.first) << " => "