diff --git a/.clang-tidy b/.clang-tidy index 93ad42fe9..847f4660f 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 8f79ed8b4..cf4970f1d 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -39,12 +39,8 @@ struct HasNoConfigurationType; template > class IDETabulationProblem : public FlowFunctions, - public NodePrinter, - public DataFlowFactPrinter, - public FunctionPrinter, public EdgeFunctions, - public JoinLattice, - public EdgeFactPrinter { + public JoinLattice { public: using ProblemAnalysisDomain = AnalysisDomainTy; using d_t = typename AnalysisDomainTy::d_t; diff --git a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h index 5c6cb2059..5deddf1f9 100644 --- a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h @@ -78,10 +78,6 @@ class IFDSTabulationProblem } EdgeFunction allTopFunction() final { return AllTop{}; } - - 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 b5a001031..60e5ae23e 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 a670a403f..484606935 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 41207a44d..669bd108d 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 6bb2c6ffa..0a9bcb327 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 780f1ea6f..512d80063 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 ae813f39f..2e835c6f5 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 8405d2030..4915cfe4f 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 b8785ebe0..518d80c7d 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 53c26627c..ac46b9068 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 8a9979b52..e2ba69e2d 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.h @@ -260,14 +260,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 26ea81ca7..9461ff4f2 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 ca75d1c12..207c9bdbe 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 14e84327c..d84f491cc 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h @@ -121,14 +121,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 9c25256ff..d4927219e 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 51663d05c..a41352335 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 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, @@ -118,11 +113,12 @@ class IDESecureHeapPropagation EdgeFunction allTopFunction() 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 cceb38a9d..2bc92e9db 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 9339ef91f..475e18ead 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h @@ -10,38 +10,137 @@ #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 IDETypeStateAnalysisBase { +public: + virtual ~IDETypeStateAnalysisBase() = default; + +protected: + IDETypeStateAnalysisBase(LLVMAliasInfoRef PT) noexcept : PT(PT) {} + + using d_t = const llvm::Value *; + using n_t = const llvm::Instruction *; + using f_t = const llvm::Function *; + using container_type = std::set; + using FlowFunctionPtrType = FlowFunctionPtrType; + + // --- 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 +149,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 override; + [[nodiscard]] bool isZeroValue(d_t Fact) const 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 +469,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 4f11609a4..0d4585614 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 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 62dcd7eb5..fc0f52a9a 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 16d7b1c59..9e3e43769 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 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 67dae0c90..5575275c4 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 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 25b7c28a5..8099e5184 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 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 9df7cf69b..49479bc1e 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 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 9c4b55c9d..3f9edcfe8 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 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 24e07c8ff..ee81523e0 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 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 ef36022a7..1f28206d1 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 0a31b6042..081b94a46 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 f038e04a6..34023c863 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 f0b0c6ab9..cb69f4fe7 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 5f06867f2..a1c41d1c2 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 a67b119ba..883b1d89d 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 4c6e0e798..df91bce7d 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 235d9a31e..8674ff564 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 c155f1b71..211de3a91 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 e62d24369..010e2f517 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 05a95b293..13c5ac42f 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 7b1f887b8..e813e38d3 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 c8f70578d..31a08cdb4 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 3f1d8d302..7aebbdb72 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 68cb0c0f4..59bd16534 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 b686680f0..6c6dba3b4 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 38c07cbf5..9c39547aa 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" @@ -324,7 +325,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 @@ -747,26 +748,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"; @@ -776,9 +757,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 a7656d23b..cfb72c540 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.cpp @@ -258,14 +258,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()) && @@ -479,27 +475,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"; @@ -627,15 +602,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 @@ -698,13 +673,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 fd4b8908e..fef29aaf6 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -568,26 +568,6 @@ EdgeFunction IDELinearConstantAnalysis::allTopFunction() { return AllTop{}; } -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 " @@ -604,11 +584,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'; @@ -652,7 +632,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"; @@ -683,15 +663,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 e40ec7a5f..a0a8619e4 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 14706b7df..116981c0a 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 { 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 @@ -213,24 +189,6 @@ IDESecureHeapPropagation::allTopFunction() { return AllTop{}; } -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; @@ -243,11 +201,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'; } @@ -257,3 +215,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 ba1d9b848..a5b37ec6f 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 5033fff0b..b646ea57f 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.cpp @@ -34,238 +34,73 @@ #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)) { if (hasMatchingType(Gep->getPointerOperand())) { - return lambdaFlow([=](d_t Source) -> std::set { - // if (Source == Gep->getPointerOperand()) { - // return {Source, Gep}; - //} - return {Source}; - }); + return identityFlow(); + // return lambdaFlow([=](d_t Source) -> std::set { + // // if (Source == Gep->getPointerOperand()) { + // // return {Source, Gep}; + // //} + // return {Source}; + // }); } } // 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 Identity::getInstance(); + 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 +111,88 @@ 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 +203,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())); @@ -416,201 +211,40 @@ IDETypeStateAnalysis::getCallToRetFlowFunction( } } } - return Identity::getInstance(); -} - -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 { - 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{}; + return identityFlow(); } -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()); } } @@ -623,11 +257,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); @@ -636,28 +268,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); @@ -667,45 +296,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; } } @@ -714,8 +336,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; } } @@ -724,76 +345,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 7a9d83212..c98996653 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysis.cpp @@ -177,21 +177,6 @@ bool IFDSConstAnalysis::isZeroValue(IFDSConstAnalysis::d_t Fact) const { 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 1f1674dc4..8b1eb7341 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 1e3f7b459..c28cb8b0e 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSProtoAnalysis.cpp @@ -78,19 +78,4 @@ bool IFDSProtoAnalysis::isZeroValue(IFDSProtoAnalysis::d_t Fact) const { 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 9bf5c0a59..2fea082af 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 { 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 6499eebb6..e67d54fbf 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 { 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 ddf60d016..4306af47c 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 { 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 53ff5c972..e798db4f2 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 { 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 2537972d9..b75979ed6 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" @@ -405,21 +406,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*/, @@ -439,13 +425,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 b6b8895ed..ba640d0ba 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 ec2957402..df37f0bcb 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 89068b96f..4c0973cf7 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 b0cc0cc87..3c0a90a67 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 f5b383ef2..e71e30b0e 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 ec4ce482b..ca19e4c6f 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 c86df2593..5d14d7fa4 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 4a9e48a99..04830d72c 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 4c223bcd7..2c415cd17 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 5becbc3c6..dc0a9782d 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 892cf558d..3d7aa3a8a 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 000000000..23910b444 --- /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 642c6fd97..f95f34ce2 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 a8bf83d15..0b2d4fa52 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 c02802f96..bc74fadfd 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 4546dc44c..a4cc5eb86 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 3006943b7..558c8007c 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) << " => "