diff --git a/include/phasar/DataFlow/IfdsIde/FlowFunctions.h b/include/phasar/DataFlow/IfdsIde/FlowFunctions.h index 87a3db452..7ff1769d7 100644 --- a/include/phasar/DataFlow/IfdsIde/FlowFunctions.h +++ b/include/phasar/DataFlow/IfdsIde/FlowFunctions.h @@ -794,6 +794,19 @@ class FlowFunctions virtual FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun, n_t ExitInst, n_t RetSite) = 0; + // Performs any side-effects of a return-flow-function + // + // In case of unbalanced returns (if the option `followReturnsPastSeeds` is + // activated in the IfdsIdeSolverConfig), we will eventually reach a function + // that is not called from other functions. Still, we may want to apply a + // return-flow-function -- just for its side-effects, such as registering a + // taint + virtual void applyUnbalancedRetFlowFunctionSideEffects(f_t CalleeFun, + n_t ExitInst, + d_t Source) { + // By default, do nothing + } + // // Describes the data-flows alongsite a CallSite. // diff --git a/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h b/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h index 484606935..b9d89a88e 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h @@ -15,6 +15,7 @@ #include "phasar/Utils/EquivalenceClassMap.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/PAMMMacros.h" +#include "phasar/Utils/Utilities.h" #include "llvm/ADT/DenseMap.h" @@ -185,6 +186,8 @@ class FlowEdgeFunctionCache { operator=(FlowEdgeFunctionCache &&FEFC) noexcept = default; FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) { + assertNotNull(Curr); + assertNotNull(Succ); PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Normal flow function factory call"); @@ -217,6 +220,8 @@ class FlowEdgeFunctionCache { } FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) { + assertNotNull(CallSite); + assertNotNull(DestFun); PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Call flow function factory call"); @@ -241,6 +246,10 @@ class FlowEdgeFunctionCache { FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun, n_t ExitInst, n_t RetSite) { + assertNotNull(CallSite); + assertNotNull(CalleeFun); + assertNotNull(ExitInst); + assertNotNull(RetSite); PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Return flow function factory call"); @@ -270,6 +279,9 @@ class FlowEdgeFunctionCache { FlowFunctionPtrType getCallToRetFlowFunction(n_t CallSite, n_t RetSite, llvm::ArrayRef Callees) { + assertNotNull(CallSite); + assertNotNull(RetSite); + assertAllNotNull(Callees); PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Call-to-Return flow function factory call"); @@ -300,6 +312,8 @@ class FlowEdgeFunctionCache { } FlowFunctionPtrType getSummaryFlowFunction(n_t CallSite, f_t DestFun) { + assertNotNull(CallSite); + assertNotNull(DestFun); // PAMM_GET_INSTANCE; // INC_COUNTER("Summary-FF Construction", 1, Full); IF_LOG_ENABLED( @@ -313,6 +327,9 @@ class FlowEdgeFunctionCache { EdgeFunction getNormalEdgeFunction(n_t Curr, d_t CurrNode, n_t Succ, d_t SuccNode) { + assertNotNull(Curr); + assertNotNull(Succ); + PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Normal edge function factory call"); @@ -357,6 +374,10 @@ class FlowEdgeFunctionCache { EdgeFunction getCallEdgeFunction(n_t CallSite, d_t SrcNode, f_t DestinationFunction, d_t DestNode) { + + assertNotNull(CallSite); + assertNotNull(DestinationFunction); + PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Call edge function factory call"); @@ -387,6 +408,11 @@ class FlowEdgeFunctionCache { EdgeFunction getReturnEdgeFunction(n_t CallSite, f_t CalleeFunction, n_t ExitInst, d_t ExitNode, n_t RetSite, d_t RetNode) { + assertNotNull(CallSite); + assertNotNull(CalleeFunction); + assertNotNull(ExitInst); + assertNotNull(RetSite); + PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Return edge function factory call"); @@ -419,6 +445,10 @@ class FlowEdgeFunctionCache { EdgeFunction getCallToRetEdgeFunction(n_t CallSite, d_t CallNode, n_t RetSite, d_t RetSiteNode, llvm::ArrayRef Callees) { + assertNotNull(CallSite); + assertNotNull(RetSite); + assertAllNotNull(Callees); + PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Call-to-Return edge function factory call"); @@ -472,6 +502,9 @@ class FlowEdgeFunctionCache { EdgeFunction getSummaryEdgeFunction(n_t CallSite, d_t CallNode, n_t RetSite, d_t RetSiteNode) { + assertNotNull(CallSite); + assertNotNull(RetSite); + PAMM_GET_INSTANCE; IF_LOG_ENABLED( PHASAR_LOG_LEVEL(DEBUG, "Summary edge function factory call"); diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h index 669bd108d..ac730de2a 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h @@ -886,8 +886,9 @@ class IDESolver // conditionally generated values should only // be propagated into callers that have an incoming edge for this // condition - if (SolverConfig.followReturnsPastSeeds() && Inc.empty() && - IDEProblem.isZeroValue(d1)) { + /// TODO: Add a check for "d1 is seed in functionOf(n)" + if (SolverConfig.followReturnsPastSeeds() && Inc.empty() /*&& + IDEProblem.isZeroValue(d1)*/) { const auto &Callers = ICF->getCallersOf(FunctionThatNeedsSummary); for (n_t Caller : Callers) { for (n_t RetSiteC : ICF->getReturnSitesOfCallAt(Caller)) { @@ -922,11 +923,8 @@ class IDESolver // the flow function has a side effect such as registering a taint; // instead we thus call the return flow function will a null caller if (Callers.empty()) { - FlowFunctionPtrType RetFunction = - CachedFlowEdgeFunctions.getRetFlowFunction( - nullptr, FunctionThatNeedsSummary, n, nullptr); - INC_COUNTER("FF Queries", 1, Full); - RetFunction->computeTargets(d2); + IDEProblem.applyUnbalancedRetFlowFunctionSideEffects( + FunctionThatNeedsSummary, n, d2); } } } diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index 8f9a71af7..9e9972ac4 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -522,7 +522,9 @@ class IDEInstInteractionAnalysisT n_t /* RetSite */) override { // Map return value back to the caller. If pointer parameters hold at the // end of a callee function generate all of those in the caller context. - + if (CallSite == nullptr) { + return this->killAllFlows(); + } auto MapFactsToCallerFF = mapFactsToCaller(llvm::cast(CallSite), ExitInst, {}, [](const llvm::Value *RetVal, d_t Src) { diff --git a/include/phasar/Utils/Utilities.h b/include/phasar/Utils/Utilities.h index 12154af21..762735bfe 100644 --- a/include/phasar/Utils/Utilities.h +++ b/include/phasar/Utils/Utilities.h @@ -14,9 +14,12 @@ #include "phasar/Utils/TypeTraits.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" +#include #include #include #include @@ -266,6 +269,26 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, return OS; } +template +LLVM_ATTRIBUTE_ALWAYS_INLINE void assertNotNull(const T &Value) {} + +template +LLVM_ATTRIBUTE_ALWAYS_INLINE void assertNotNull(const std::optional &Value) { + assert(Value.has_value()); +} + +template +LLVM_ATTRIBUTE_ALWAYS_INLINE void assertNotNull(const T *Value) { + assert(Value != nullptr); +} + +template void assertAllNotNull(const T &Range) { + assertNotNull(Range); + for (const auto &Elem : Range) { + assertNotNull(Elem); + } +} + } // namespace psr #endif