From 2ef13bb075a9511a55f915332f0695ab51b72158 Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Tue, 4 Aug 2026 16:39:53 +0300 Subject: [PATCH 01/12] Introduce call resolution success fact propagation --- .../dataflow/ap/ifds/MethodAnalyzer.kt | 118 ++++++- .../ap/ifds/MethodAnalyzerEdgeSearcher.kt | 3 +- .../ap/ifds/analysis/AnalysisManager.kt | 7 + .../ifds/analysis/MethodCallFlowFunction.kt | 132 +++++++- .../ap/ifds/trace/MethodCallPrecondition.kt | 35 +- .../MethodCallSummaryPreconditionHandler.kt | 7 + .../ap/ifds/trace/MethodTraceResolver.kt | 317 +++++++++++------- .../dataflow/go/analysis/GoAnalysisManager.kt | 8 + .../GoCallRuleBasedSummaryRewriter.kt | 5 +- .../go/analysis/GoMethodCallFlowFunction.kt | 14 +- .../go/trace/GoMethodCallPrecondition.kt | 27 +- .../GoMethodCallSummaryPreconditionHandler.kt | 5 + .../ap/ifds/analysis/JIRAnalysisManager.kt | 8 + .../analysis/JIRMethodCallFlowFunction.kt | 15 +- .../JIRMethodCallRuleBasedSummaryRewriter.kt | 5 +- .../ifds/trace/JIRMethodCallPrecondition.kt | 27 +- ...JIRMethodCallSummaryPreconditionHandler.kt | 5 + .../taint/TaintRuleGenerationCtx.kt | 3 +- 18 files changed, 556 insertions(+), 185 deletions(-) create mode 100644 core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt create mode 100644 core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt create mode 100644 core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index 9dcfabcbc..4be8a15c2 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -142,10 +142,12 @@ interface MethodAnalyzer { fun resetApManager(apManager: ApManager) sealed interface MethodCallHandler { - data class ZeroToZeroHandler(val currentEdge: ZeroToZero) : MethodCallHandler - data class ZeroToFactHandler(val currentEdge: ZeroToFact, val startFactBase: AccessPathBase) : MethodCallHandler - data class FactToFactHandler(val currentEdge: FactToFact, val startFactBase: AccessPathBase) : MethodCallHandler - data class NDFactToFactHandler(val currentEdge: NDFactToFact, val startFactBase: AccessPathBase) : MethodCallHandler + val currentEdge: Edge + + data class ZeroToZeroHandler(override val currentEdge: ZeroToZero) : MethodCallHandler + data class ZeroToFactHandler(override val currentEdge: ZeroToFact, val startFactBase: AccessPathBase) : MethodCallHandler + data class FactToFactHandler(override val currentEdge: FactToFact, val startFactBase: AccessPathBase) : MethodCallHandler + data class NDFactToFactHandler(override val currentEdge: NDFactToFact, val startFactBase: AccessPathBase) : MethodCallHandler } sealed interface MethodCallResolutionFailureHandler { @@ -537,6 +539,68 @@ class NormalMethodAnalyzer( } } + private fun propagateZeroCallSuccessFact( + callExpr: CommonCallExpr, + edge: ZeroInitialEdge, + fact: MethodCallFlowFunction.ZeroCallSuccessFact, + ep: MethodEntryPoint, + ) { + when (fact) { + is MethodCallFlowFunction.CallToStartZeroFact -> { + val callerEdge = ZeroToZero(methodEntryPoint, edge.statement) + runner.subscribeOnMethodSummaries(callerEdge, ep) + } + + is MethodCallFlowFunction.CallToStartZFact -> { + val callerEdge = ZeroToFact(methodEntryPoint, edge.statement, fact.callerFactAp) + runner.subscribeOnMethodSummaries(callerEdge, ep, fact.startFactBase) + } + + is MethodCallFlowFunction.CallToReturnFFact, + is MethodCallFlowFunction.CallToReturnNonDistributiveFact, + is MethodCallFlowFunction.CallToReturnZFact, + is MethodCallFlowFunction.CallToReturnZeroFact -> propagateZeroCallFact(callExpr, edge, fact) + } + } + + private fun propagateFactCallSuccessFact( + callExpr: CommonCallExpr, + edge: FactToFact, + fact: MethodCallFlowFunction.FactCallSuccessFact, + ep: MethodEntryPoint, + ) { + when (fact) { + is MethodCallFlowFunction.CallToStartFFact -> { + val callerEdge = FactToFact(methodEntryPoint, fact.initialFactAp, edge.statement, fact.callerFactAp) + handleInputFactChange(edge.initialFactAp, callerEdge.initialFactAp) + runner.subscribeOnMethodSummaries(callerEdge, ep, fact.startFactBase) + } + + is MethodCallFlowFunction.CallToReturnFFact, + is MethodCallFlowFunction.CallToReturnZFact, + is MethodCallFlowFunction.CallToReturnNonDistributiveFact, + is MethodCallFlowFunction.SideEffectRequirement, + is MethodCallFlowFunction.FactSideEffect -> propagateFactCallFact(callExpr, edge, fact) + } + } + + private fun propagateNDFactCallSuccessFact( + callExpr: CommonCallExpr, + edge: NDFactToFact, + fact: MethodCallFlowFunction.NDFactCallSuccessFact, + ep: MethodEntryPoint, + ) { + when (fact) { + is MethodCallFlowFunction.CallToStartNDFFact -> { + val callerEdge = NDFactToFact(methodEntryPoint, fact.initialFacts, edge.statement, fact.callerFactAp) + runner.subscribeOnMethodSummaries(callerEdge, ep, fact.startFactBase) + } + + is MethodCallFlowFunction.CallToReturnZFact, + is MethodCallFlowFunction.CallToReturnNonDistributiveFact -> propagateNDFactCallFact(callExpr, edge, fact) + } + } + private fun addInitialZeroEdge() { val edge = ZeroToZero(methodEntryPoint, methodEntryPoint.statement) addSequentialEdge(edge) @@ -752,18 +816,46 @@ class NormalMethodAnalyzer( handleMethodCall(handler, entryPoint) } - private fun handleMethodCall(handler: MethodCallHandler, ep: MethodEntryPoint) = when (handler) { - is MethodCallHandler.ZeroToZeroHandler -> - runner.subscribeOnMethodSummaries(handler.currentEdge, ep) + private fun handleMethodCall(handler: MethodCallHandler, ep: MethodEntryPoint) { + val statement = handler.currentEdge.statement + val callExpr = analysisManager.getCallExpr(statement) ?: error("Expected call expression") + val returnValue: CommonValue? = (statement as? CommonAssignInst)?.lhv + val flowFunction = analysisManager.getMethodCallFlowFunction( + apManager, + analysisContext, + returnValue, + callExpr, + statement, + generateTrace = false, + ) + + return when (handler) { + is MethodCallHandler.ZeroToZeroHandler -> { + flowFunction.propagateZeroToZeroResolutionSuccess(ep).forEach { + propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, ep) + } + } - is MethodCallHandler.ZeroToFactHandler -> - runner.subscribeOnMethodSummaries(handler.currentEdge, ep, handler.startFactBase) + is MethodCallHandler.ZeroToFactHandler -> { + flowFunction.propagateZeroToFactResolutionSuccess(handler.currentEdge.factAp, handler.startFactBase, ep).forEach { + propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, ep) + } + } - is MethodCallHandler.FactToFactHandler -> - runner.subscribeOnMethodSummaries(handler.currentEdge, ep, handler.startFactBase) + is MethodCallHandler.FactToFactHandler -> { + val edge = handler.currentEdge + flowFunction.propagateFactToFactResolutionSuccess(edge.initialFactAp, edge.factAp, handler.startFactBase, ep).forEach { + propagateFactCallSuccessFact(callExpr, edge, it, ep) + } + } - is MethodCallHandler.NDFactToFactHandler -> - runner.subscribeOnMethodSummaries(handler.currentEdge, ep, handler.startFactBase) + is MethodCallHandler.NDFactToFactHandler -> { + val edge = handler.currentEdge + flowFunction.propagateNDFactToFactResolutionSuccess(edge.initialFacts, edge.factAp, handler.startFactBase, ep).forEach { + propagateNDFactCallSuccessFact(callExpr, edge, it, ep) + } + } + } } override fun handleMethodCallResolutionFailure( diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt index ae3fa9de5..3d2443aeb 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt @@ -6,6 +6,7 @@ import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.AnalysisManager import org.opentaint.dataflow.ap.ifds.analysis.MethodAnalysisContext import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondition +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.PreconditionFactsForInitialFact import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition.SequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition.SequentPreconditionFacts @@ -104,7 +105,7 @@ abstract class MethodAnalyzerEdgeSearcher( ) val preconditions = preconditionFunction.factPrecondition(fact) - return preconditions.queryResult<_, CallPrecondition.Unchanged, PreconditionFactsForInitialFact> { initialFact } + return preconditions.queryResult<_, CallPrecondition.Unchanged, PreconditionFactsForInitialFact> { initialFact } } else { val preconditionFunction = analysisManager.getMethodSequentPrecondition( apManager, analysisContext, statement diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt index c11decfd2..f1f276fd0 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt @@ -10,6 +10,7 @@ import org.opentaint.dataflow.ap.ifds.TaintAnalysisUnitRunner import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodStartPrecondition import org.opentaint.dataflow.graph.MethodInstGraph @@ -90,6 +91,12 @@ interface AnalysisManager: LanguageManager { statement: CommonInst, ): MethodCallSummaryHandler + fun getMethodCallSummaryPreconditionHandler( + apManager: ApManager, + analysisContext: MethodAnalysisContext, + statement: CommonInst, + ): MethodCallSummaryPreconditionHandler + fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt index 6ccd5edd5..83e6c1075 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt @@ -2,6 +2,7 @@ package org.opentaint.dataflow.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.ExclusionSet +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.SideEffectKind import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -26,53 +27,59 @@ interface MethodCallFlowFunction { sealed interface NDFactCallFailureFact: NDFactCallFact + sealed interface ZeroCallSuccessFact + + sealed interface FactCallSuccessFact + + sealed interface NDFactCallSuccessFact + data object Unchanged : ZeroCallFact, FactCallFact, NDFactCallFact - data object CallToReturnZeroFact: ZeroCallFact, Call2ReturnFact, ZeroCallFailureFact + data object CallToReturnZeroFact: ZeroCallFact, Call2ReturnFact, ZeroCallFailureFact, ZeroCallSuccessFact - data object CallToStartZeroFact : ZeroCallFact + data object CallToStartZeroFact : ZeroCallFact, ZeroCallSuccessFact data class CallToReturnFFact( val initialFactAp: InitialFactAp, val factAp: FinalFactAp, val traceInfo: TraceInfo?, - ) : FactCallFact, ZeroCallFact, Call2ReturnFact, FactCallFailureFact, ZeroCallFailureFact + ) : FactCallFact, ZeroCallFact, Call2ReturnFact, FactCallFailureFact, ZeroCallFailureFact, ZeroCallSuccessFact, FactCallSuccessFact data class CallToStartFFact( val initialFactAp: InitialFactAp, val callerFactAp: FinalFactAp, val startFactBase: AccessPathBase, val traceInfo: TraceInfo?, - ) : FactCallFact + ) : FactCallFact, FactCallSuccessFact data class CallToReturnZFact( val factAp: FinalFactAp, val traceInfo: TraceInfo?, - ) : ZeroCallFact, FactCallFact, NDFactCallFact, Call2ReturnFact, ZeroCallFailureFact, FactCallFailureFact, NDFactCallFailureFact + ) : ZeroCallFact, FactCallFact, NDFactCallFact, Call2ReturnFact, ZeroCallFailureFact, FactCallFailureFact, NDFactCallFailureFact, ZeroCallSuccessFact, FactCallSuccessFact, NDFactCallSuccessFact data class CallToStartZFact( val callerFactAp: FinalFactAp, val startFactBase: AccessPathBase, val traceInfo: TraceInfo?, - ) : ZeroCallFact + ) : ZeroCallFact, ZeroCallSuccessFact data class CallToReturnNonDistributiveFact( val initialFacts: Set, val factAp: FinalFactAp, val traceInfo: TraceInfo?, - ) : FactCallFact, ZeroCallFact, NDFactCallFact, Call2ReturnFact, FactCallFailureFact, ZeroCallFailureFact, NDFactCallFailureFact + ) : FactCallFact, ZeroCallFact, NDFactCallFact, Call2ReturnFact, FactCallFailureFact, ZeroCallFailureFact, NDFactCallFailureFact, ZeroCallSuccessFact, FactCallSuccessFact, NDFactCallSuccessFact data class CallToStartNDFFact( val initialFacts: Set, val callerFactAp: FinalFactAp, val startFactBase: AccessPathBase, val traceInfo: TraceInfo?, - ) : NDFactCallFact + ) : NDFactCallFact, NDFactCallSuccessFact - data class SideEffectRequirement(val initialFactAp: InitialFactAp) : FactCallFact, FactCallFailureFact + data class SideEffectRequirement(val initialFactAp: InitialFactAp) : FactCallFact, FactCallFailureFact, FactCallSuccessFact data class ZeroSideEffect(val kind: SideEffectKind) : ZeroCallFact, ZeroCallFailureFact - data class FactSideEffect(val initialFactAp: InitialFactAp, val kind: SideEffectKind) : FactCallFact, FactCallFailureFact + data class FactSideEffect(val initialFactAp: InitialFactAp, val kind: SideEffectKind) : FactCallFact, FactCallFailureFact, FactCallSuccessFact data class Drop( val traceInfo: TraceInfo?, @@ -93,6 +100,11 @@ interface MethodCallFlowFunction { fun propagateFactToFactResolutionFailure(initialFactAp: InitialFactAp, currentFactAp: FinalFactAp, startFactBase: AccessPathBase): Set fun propagateNDFactToFactResolutionFailure(initialFacts: Set, currentFactAp: FinalFactAp, startFactBase: AccessPathBase): Set + fun propagateZeroToZeroResolutionSuccess(ep: MethodEntryPoint): Set + fun propagateZeroToFactResolutionSuccess(currentFactAp: FinalFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): Set + fun propagateFactToFactResolutionSuccess(initialFactAp: InitialFactAp, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): Set + fun propagateNDFactToFactResolutionSuccess(initialFacts: Set, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): Set + interface Default : MethodCallFlowFunction { override fun propagateZeroToFact(currentFactAp: FinalFactAp) = buildSet { propagateFact( @@ -187,6 +199,7 @@ interface MethodCallFlowFunction { override fun propagateZeroToFactResolutionFailure(currentFactAp: FinalFactAp, startFactBase: AccessPathBase) = buildSet { propagateUnresolvedCallFact( factAp = currentFactAp, + startFactBase = startFactBase, addSideEffectRequirement = { factReader -> check(!factReader.hasRefinement) { "Can't refine Zero fact" } }, @@ -204,6 +217,7 @@ interface MethodCallFlowFunction { ): Set = buildSet { propagateUnresolvedCallFact( factAp = currentFactAp, + startFactBase = startFactBase, addSideEffectRequirement = { factReader -> this += SideEffectRequirement(factReader.refineFact(initialFactAp.replaceExclusions(ExclusionSet.Empty))) }, @@ -224,6 +238,7 @@ interface MethodCallFlowFunction { ) = buildSet { propagateUnresolvedCallFact( factAp = currentFactAp, + startFactBase = startFactBase, addSideEffectRequirement = { factReader -> check(!factReader.hasRefinement) { "Can't refine NDF2F edge" } }, @@ -234,6 +249,92 @@ interface MethodCallFlowFunction { ) } + override fun propagateZeroToZeroResolutionSuccess(ep: MethodEntryPoint): Set = + setOf(CallToStartZeroFact) + + override fun propagateZeroToFactResolutionSuccess( + currentFactAp: FinalFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint, + ): Set = buildSet { + propagateSuccessCallFact( + factAp = currentFactAp, + startFactBase = startFactBase, + ep = ep, + addSideEffectRequirement = { factReader -> + check(!factReader.hasRefinement) { "Can't refine Zero fact" } + }, + addCallToReturn = { factReader, factAp, trace -> + check(!factReader.hasRefinement) { "Can't refine Zero fact" } + this += CallToReturnZFact(factAp, trace) + }, + addCallToStart = { callerFactAp, startFactBase, trace -> + this += CallToStartZFact(callerFactAp, startFactBase, trace) + }, + addUnchecked = { + check(it is ZeroCallSuccessFact) { "unexpected" } + this += it + }, + ) + } + + override fun propagateFactToFactResolutionSuccess( + initialFactAp: InitialFactAp, + currentFactAp: FinalFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint, + ): Set = buildSet { + propagateSuccessCallFact( + factAp = currentFactAp, + startFactBase = startFactBase, + ep = ep, + addSideEffectRequirement = { factReader -> + this += SideEffectRequirement(factReader.refineFact(initialFactAp.replaceExclusions(ExclusionSet.Empty))) + }, + addCallToReturn = { factReader, factAp, trace -> + this += CallToReturnFFact( + factReader.refineFact(initialFactAp), + factReader.refineFact(factAp), + trace + ) + }, + addCallToStart = { callerFactAp, startFactBase, trace -> + this += CallToStartFFact(initialFactAp, callerFactAp, startFactBase, trace) + }, + addUnchecked = { + check(it is FactCallSuccessFact) { "unexpected" } + this += it + }, + ) + } + + override fun propagateNDFactToFactResolutionSuccess( + initialFacts: Set, + currentFactAp: FinalFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint, + ): Set = buildSet { + propagateSuccessCallFact( + factAp = currentFactAp, + startFactBase = startFactBase, + ep = ep, + addSideEffectRequirement = { factReader -> + check(!factReader.hasRefinement) { "Can't refine NDF2F edge" } + }, + addCallToReturn = { factReader, factAp, trace -> + check(!factReader.hasRefinement) { "Can't refine NDF2F edge" } + this += CallToReturnNonDistributiveFact(initialFacts, factAp, trace) + }, + addCallToStart = { callerFactAp, startFactBase, trace -> + this += CallToStartNDFFact(initialFacts, callerFactAp, startFactBase, trace) + }, + addUnchecked = { + check(it is NDFactCallSuccessFact) { "unexpected" } + this += it + }, + ) + } + fun propagateFact( initialFacts: Set, exclusion: ExclusionSet, @@ -247,8 +348,19 @@ interface MethodCallFlowFunction { fun propagateUnresolvedCallFact( factAp: FinalFactAp, + startFactBase: AccessPathBase, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, addSideEffectRequirement: (FinalFactReader) -> Unit, ) + + fun propagateSuccessCallFact( + factAp: FinalFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint, + addSideEffectRequirement: (FinalFactReader) -> Unit, + addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, + addCallToStart: (callerFact: FinalFactAp, startFactBase: AccessPathBase, TraceInfo?) -> Unit, + addUnchecked: (CallFact) -> Unit, + ) } } diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt index 71c1efda6..0c31d4125 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt @@ -2,10 +2,11 @@ package org.opentaint.dataflow.ap.ifds.trace import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.MethodAnalyzerEdges +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp -import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact.CallFailurePreconditionFact +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondition import org.opentaint.dataflow.ap.ifds.trace.TaintRulePrecondition.PassRuleCondition import org.opentaint.dataflow.taint.PreconditionCube import org.opentaint.dataflow.taint.TaintMarkAwareConditionExpr @@ -13,25 +14,29 @@ import org.opentaint.dataflow.taint.preconditionDnf import org.opentaint.ir.api.common.cfg.CommonInst interface MethodCallPrecondition { - sealed interface CallPrecondition { - data object Unchanged : CallPrecondition + sealed interface CallPrecondition { + data object Unchanged : CallPrecondition } - data class PreconditionFactsForInitialFact( + data class PreconditionFactsForInitialFact( val initialFact: InitialFactAp, - val preconditionFacts: List, - ): CallPrecondition + val preconditionFacts: List, + ): CallPrecondition - sealed interface CallPreconditionFact { - sealed interface CallFailurePreconditionFact : CallPreconditionFact + sealed interface CallPreconditionFact + sealed interface CallResolutionPreconditionFact - object UnresolvedCallSkip : CallPreconditionFact, CallFailurePreconditionFact - data class CallToReturnTaintRule(val precondition: TaintRulePrecondition) : CallPreconditionFact, CallFailurePreconditionFact - data class CallToStart(val callerFact: InitialFactAp, val startFactBase: AccessPathBase) : CallPreconditionFact - } + sealed interface CallFailurePreconditionFact : CallResolutionPreconditionFact + sealed interface CallSuccessPreconditionFact : CallResolutionPreconditionFact + + object UnresolvedCallSkip : CallPreconditionFact, CallFailurePreconditionFact + data class CallToReturnTaintRule(val precondition: TaintRulePrecondition) : CallPreconditionFact, CallFailurePreconditionFact, CallSuccessPreconditionFact + data class CallToStart(val callerFact: InitialFactAp, val startFactBase: AccessPathBase) : CallPreconditionFact + data class CallToStartResolved(val callerFact: InitialFactAp, val startFactBase: AccessPathBase, val method: MethodEntryPoint): CallSuccessPreconditionFact - fun factPrecondition(fact: InitialFactAp): List + fun factPrecondition(fact: InitialFactAp): List> fun factPreconditionResolutionFailure(fact: InitialFactAp, startFactBase: AccessPathBase): List + fun factPreconditionResolutionSuccess(fact: InitialFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): List data class PassRuleConditionFacts(val facts: List) @@ -79,3 +84,7 @@ interface MethodCallPrecondition { preconditionDnf(apManager, { allRelevantFacts(edges, it) }) { mapExit2Return(it) } } } + +@Suppress("UNCHECKED_CAST") +fun mkUnchanged(): CallPrecondition = + CallPrecondition.Unchanged as CallPrecondition diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt new file mode 100644 index 000000000..41c23ba05 --- /dev/null +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt @@ -0,0 +1,7 @@ +package org.opentaint.dataflow.ap.ifds.trace + +import org.opentaint.dataflow.ap.ifds.Edge + +interface MethodCallSummaryPreconditionHandler { + fun prepareFactToFactSummary(summaryEdge: Edge.FactToFact): List = listOf(summaryEdge) +} diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt index 06d5386eb..058ff7bdf 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt @@ -23,7 +23,9 @@ import org.opentaint.dataflow.ap.ifds.analysis.MethodAnalysisContext import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFactMapper import org.opentaint.dataflow.ap.ifds.analysis.MethodCallResolver.MethodCallResolutionResult import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondition +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallResolutionPreconditionFact import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.PreconditionFactsForInitialFact import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition.SequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodTraceResolver.PartiallyResolvedMergedCallAction.MergedPrimaryCall2StartAction import org.opentaint.dataflow.ap.ifds.trace.MethodTraceResolver.PartiallyResolvedMergedCallAction.MergedPrimaryUnresolvedCallSkip @@ -63,6 +65,7 @@ import org.opentaint.ir.api.common.cfg.CommonValue import java.util.BitSet import java.util.LinkedList import java.util.Objects +import kotlin.collections.plusAssign class MethodTraceResolver( private val runner: AnalysisRunner, @@ -890,20 +893,17 @@ class MethodTraceResolver( val preconditionFunction = analysisManager.getMethodCallPrecondition( apManager, analysisContext, returnValue, statementCall, statement ) - val callees by lazy { - runner.methodCallResolver.resolvedMethodCalls(analysisContext, statementCall, statement) - } val callEdges = mutableListOf>>() for (edge in entry.edges) { - val preconditions = callFactPrecondition(preconditionFunction, edge.fact, callees) + val preconditions = preconditionFunction.factPrecondition(edge.fact) val callActions = mutableListOf>() for (precondition in preconditions) { when (precondition) { is CallPrecondition.Unchanged -> callActions += ActionOrUnchanged.Unchanged(edge) - is MethodCallPrecondition.PreconditionFactsForInitialFact -> { + is PreconditionFactsForInitialFact -> { val initialEdge = edge.replaceFact(precondition.initialFact) if (!skipFactCheck && !containsEntryEdge(entry.statement, initialEdge)) { continue @@ -933,16 +933,11 @@ class MethodTraceResolver( } val resolvedMethods by lazy { - callees.mapNotNull { - when (it) { - is MethodCallResolutionResult.ResolvedMethod -> it.method - MethodCallResolutionResult.ResolutionFailure -> null - } - } + runner.methodCallResolver.resolvedMethodCalls(analysisContext, statementCall, statement) } val resolvedCallActions = mutableListOf() - forEachMergedCallActionsCombination(callEdges, resolvedMethods) { callAction -> + forEachMergedCallActionsCombination(callEdges, preconditionFunction, { resolvedMethods }) { callAction -> resolvedCallActions.resolveCallAction(preconditionFunction, statement, callAction) } @@ -1009,54 +1004,6 @@ class MethodTraceResolver( } } - private fun callFactPrecondition( - preconditionFunction: MethodCallPrecondition, - fact: InitialFactAp, - callees: List, - ): List = buildList { - val preconditions = preconditionFunction.factPrecondition(fact) - - preconditions.forEach { precondition -> - when (precondition) { - CallPrecondition.Unchanged -> { - this += precondition - } - - is MethodCallPrecondition.PreconditionFactsForInitialFact -> { - this += processCallPreconditionFacts(preconditionFunction, precondition, callees) - } - } - } - } - - private fun processCallPreconditionFacts( - preconditionFunction: MethodCallPrecondition, - precondition: MethodCallPrecondition.PreconditionFactsForInitialFact, - callees: List, - ): MethodCallPrecondition.PreconditionFactsForInitialFact { - val resolutionFailure by lazy { callees.any { it is MethodCallResolutionResult.ResolutionFailure } } - - val processedPreconditions = precondition.preconditionFacts.flatMapTo(hashSetOf()) { preconditionFact -> - when (preconditionFact) { - is CallPreconditionFact.UnresolvedCallSkip -> listOf(preconditionFact) - is CallPreconditionFact.CallToReturnTaintRule -> listOf(preconditionFact) - - is CallPreconditionFact.CallToStart -> { - if (resolutionFailure) { - preconditionFunction.factPreconditionResolutionFailure( - precondition.initialFact, - preconditionFact.startFactBase - ) + preconditionFact - } else { - listOf(preconditionFact) - } - } - } - }.toList() - - return MethodCallPrecondition.PreconditionFactsForInitialFact(precondition.initialFact, processedPreconditions) - } - private fun TraceBuilder.addPredecessorActions( actionsCombination: List, entry: TraceEntry, @@ -1181,23 +1128,129 @@ class MethodTraceResolver( private inline fun forEachMergedCallActionsCombination( callActions: List>>, - callees: List, + preconditionFunction: MethodCallPrecondition, + callees: () -> List, body: (PartialCallEdgeCombination) -> Unit, ) { callActions.forEachCartesianProduct { actions -> - val mergedActions = mergeCallActions(actions) { callees } - mergedActions.forEach(body) + resolveCall2StartActions(actions, preconditionFunction, callees) { boundActions -> + boundActions.forEachCartesianProduct { resolvedActions -> + mergeCallActions(resolvedActions)?.let { body(it) } + } + } + } + } + + private inline fun resolveCall2StartActions( + actions: Array>, + preconditionFunction: MethodCallPrecondition, + callees: () -> List, + process: (List>>) -> Unit, + ) { + val methodResolutionIsRequired = actions.any { it is ActionOrUnchanged.Action && it.action is PartiallyResolvedCallAction.Call2Start } + + if (!methodResolutionIsRequired) { + process(resolveCall2StartNoCalls(actions)) + return + } + + val resolvedCallees = callees() + resolvedCallees.forEach { callee -> + when (callee) { + is MethodCallResolutionResult.ResolutionFailure -> { + val expandedActions = resolveCall2StartFailure(actions, preconditionFunction) + process(expandedActions) + } + + is MethodCallResolutionResult.ResolvedMethod -> { + methodEntryPoints(callee.method).forEach { + val expandedActions = resolveCall2StartSuccess(actions, preconditionFunction, it) + process(expandedActions) + } + } + } + } + } + + private fun resolveCall2StartSuccess( + actions: Array>, + preconditionFunction: MethodCallPrecondition, + ep: MethodEntryPoint + ): List>> = resolveCall2StartActions(actions) { callerFact, base -> + preconditionFunction.factPreconditionResolutionSuccess(callerFact, base, ep) + } + + private fun resolveCall2StartFailure( + actions: Array>, + preconditionFunction: MethodCallPrecondition, + ): List>> = resolveCall2StartActions(actions) { callerFact, base -> + preconditionFunction.factPreconditionResolutionFailure(callerFact, base) + } + + private fun resolveCall2StartNoCalls( + actions: Array> + ): List>> = resolveCall2StartActions(actions) { _, _ -> + error("Unexpected call") + } + + @Suppress("UNCHECKED_CAST") + private inline fun resolveCall2StartActions( + actions: Array>, + call2StartPreconditions: (InitialFactAp, AccessPathBase) -> List, + ): List>> { + return actions.map { action -> + when (action) { + is ActionOrUnchanged.Unchanged -> listOf(action as ActionOrUnchanged.Unchanged) + + is ActionOrUnchanged.Action -> { + collectToListWithPostProcess( + mutableListOf(), + { it.resolveCall2StartAction(action.action, call2StartPreconditions) }, + { ActionOrUnchanged.Action(it) } + ) + } + } + } + } + + private inline fun MutableList.resolveCall2StartAction( + action: PartiallyResolvedCallAction, + call2StartPreconditions: (InitialFactAp, AccessPathBase) -> List, + ) { + val currentEdge = action.currentEdge + + when (action) { + is PartiallyResolvedCallAction.CallRule -> this += PartiallyResolvedBoundCallAction.CallRule(currentEdge, action.rule) + + is PartiallyResolvedCallAction.UnresolvedCallSkip -> this += PartiallyResolvedBoundCallAction.UnresolvedCallSkip(currentEdge) + + is PartiallyResolvedCallAction.Call2Start -> { + call2StartPreconditions(action.call2Start.callerFact, action.call2Start.startFactBase).forEach { fact -> + when (fact) { + is MethodCallPrecondition.UnresolvedCallSkip -> this += PartiallyResolvedBoundCallAction.UnresolvedCallSkip(currentEdge) + + is MethodCallPrecondition.CallToReturnTaintRule -> { + if (skipRulePropagation(fact, currentEdge)) return@forEach + + this += PartiallyResolvedBoundCallAction.CallRule(currentEdge, fact.precondition) + } + + is MethodCallPrecondition.CallToStartResolved -> { + this += PartiallyResolvedBoundCallAction.Call2Start(currentEdge, fact) + } + } + } + } } } private fun mergeCallActions( - aouGroup: Array>, - resolveMethodCallees: () -> List - ): List { + aouGroup: Array>, + ): PartialCallEdgeCombination? { val unchanged = hashSetOf() - val rules = hashSetOf() - val summary = hashSetOf() - val unresolvedSkips = hashSetOf() + val rules = hashSetOf() + val summary = hashSetOf() + val unresolvedSkips = hashSetOf() for (aou in aouGroup) { when (aou) { @@ -1206,9 +1259,9 @@ class MethodTraceResolver( } is ActionOrUnchanged.Action -> when (val action = aou.action) { - is PartiallyResolvedCallAction.CallRule -> rules.add(action) - is PartiallyResolvedCallAction.Call2Start -> summary.add(action) - is PartiallyResolvedCallAction.UnresolvedCallSkip -> { unresolvedSkips.add(action) } + is PartiallyResolvedBoundCallAction.CallRule -> rules.add(action) + is PartiallyResolvedBoundCallAction.Call2Start -> summary.add(action) + is PartiallyResolvedBoundCallAction.UnresolvedCallSkip -> { unresolvedSkips.add(action) } } } } @@ -1217,33 +1270,26 @@ class MethodTraceResolver( if (summary.isEmpty()) { if (unresolvedSkips.isEmpty()) { - return listOf(PartialCallEdgeCombination(unchanged, primary = null, mergedRules)) + return PartialCallEdgeCombination(unchanged, primary = null, mergedRules) } val skippedEdges = unresolvedSkips.mapTo(hashSetOf()) { it.currentEdge } val primary = MergedPrimaryUnresolvedCallSkip(UnresolvedCallSkip(skippedEdges, skippedEdges)) - return listOf(PartialCallEdgeCombination(unchanged, primary, mergedRules)) + return PartialCallEdgeCombination(unchanged, primary, mergedRules) } if (unresolvedSkips.isNotEmpty()) { // note: we have a summary (i.e. call resolved) and an unresolved call - return emptyList() - } - - val callees = resolveMethodCallees() - - val result = mutableListOf() - callees.forEach { callee -> - methodEntryPoints(callee).forEach { - val primary = MergedPrimaryCall2StartAction(it, summary) - result += PartialCallEdgeCombination(unchanged, primary, mergedRules) - } + return null } - return result + // all summaries have the same entry-point + val ep = summary.first().call2Start.method + val primary = MergedPrimaryCall2StartAction(ep, summary) + return PartialCallEdgeCombination(unchanged, primary, mergedRules) } - private fun mergeCallRules(callRules: HashSet): Set { + private fun mergeCallRules(callRules: HashSet): Set { if (callRules.isEmpty()) return emptySet() val sourceRules = hashMapOf>>() @@ -1281,27 +1327,45 @@ class MethodTraceResolver( } private sealed interface PartiallyResolvedCallAction { + val currentEdge: TraceEdge + data class CallRule( - val currentEdge: TraceEdge, + override val currentEdge: TraceEdge, val rule: TaintRulePrecondition ) : PartiallyResolvedCallAction data class Call2Start( - val currentEdge: TraceEdge, - val call2Start: CallPreconditionFact.CallToStart, + override val currentEdge: TraceEdge, + val call2Start: MethodCallPrecondition.CallToStart, ): PartiallyResolvedCallAction data class UnresolvedCallSkip( - val currentEdge: TraceEdge, + override val currentEdge: TraceEdge, ): PartiallyResolvedCallAction } + private sealed interface PartiallyResolvedBoundCallAction { + data class CallRule( + val currentEdge: TraceEdge, + val rule: TaintRulePrecondition + ) : PartiallyResolvedBoundCallAction + + data class Call2Start( + val currentEdge: TraceEdge, + val call2Start: MethodCallPrecondition.CallToStartResolved, + ): PartiallyResolvedBoundCallAction + + data class UnresolvedCallSkip( + val currentEdge: TraceEdge, + ): PartiallyResolvedBoundCallAction + } + private sealed interface PartiallyResolvedMergedCallAction { sealed interface PartiallyResolvedMergedPrimaryCallAction: PartiallyResolvedMergedCallAction data class MergedPrimaryCall2StartAction( val calleeEntryPoint: MethodEntryPoint, - val call2Start: Set, + val call2Start: Set, ) : PartiallyResolvedMergedPrimaryCallAction data class MergedPrimaryUnresolvedCallSkip( @@ -1314,26 +1378,27 @@ class MethodTraceResolver( ) : PartiallyResolvedMergedCallAction } + private fun skipRulePropagation(fact: MethodCallPrecondition.CallToReturnTaintRule, currentEdge: TraceEdge) = + // We search for pass-rule, not source rule + fact.precondition is TaintRulePrecondition.Source && currentEdge !is TraceEdge.SourceTraceEdge + private fun MutableList.propagateCall( currentEdge: TraceEdge, - preconditionFacts: List + preconditionFacts: List, ) { for (fact in preconditionFacts) { when (fact) { - is CallPreconditionFact.CallToReturnTaintRule -> { - if (fact.precondition is TaintRulePrecondition.Source && currentEdge !is TraceEdge.SourceTraceEdge) { - // We search for pass-rule, not source rule - continue - } + is MethodCallPrecondition.CallToReturnTaintRule -> { + if (skipRulePropagation(fact, currentEdge)) continue this += PartiallyResolvedCallAction.CallRule(currentEdge, fact.precondition) } - is CallPreconditionFact.CallToStart -> { + is MethodCallPrecondition.CallToStart -> { this += PartiallyResolvedCallAction.Call2Start(currentEdge, fact) } - is CallPreconditionFact.UnresolvedCallSkip -> { + is MethodCallPrecondition.UnresolvedCallSkip -> { this += PartiallyResolvedCallAction.UnresolvedCallSkip(currentEdge) } } @@ -1381,7 +1446,7 @@ class MethodTraceResolver( private fun resolveCallSummary( statement: CommonInst, callee: MethodEntryPoint, - call2Start: Set, + call2Start: Set, ): List { val resultSummaries = mutableListOf>() for (action in call2Start) { @@ -1573,9 +1638,10 @@ class MethodTraceResolver( private fun MutableList.resolveCallPassSummary( currentEdge: TraceEdge, callee: MethodEntryPoint, - startFact: CallPreconditionFact.CallToStart, + startFact: MethodCallPrecondition.CallToStartResolved, statement: CommonInst ) { + val summaryHandler = analysisManager.getMethodCallSummaryPreconditionHandler(apManager, analysisContext, statement) val resolvedCallSummaries = mutableListOf() val methodSummaries = manager.findFactToFactSummaryEdges(callee, startFact.startFactBase) @@ -1588,28 +1654,31 @@ class MethodTraceResolver( if (deltas.isEmpty()) continue - // it is ok to map call arguments via exit2return - val mappedSummaryInitial = methodCallFactMapper.mapMethodExitToReturnFlowFact( - statement, summaryEdge.initialFactAp - ) + val applicableSummaries = summaryHandler.prepareFactToFactSummary(summaryEdge) + applicableSummaries.forEach { applicableSummary -> + // it is ok to map call arguments via exit2return + val mappedSummaryInitial = methodCallFactMapper.mapMethodExitToReturnFlowFact( + statement, applicableSummary.initialFactAp + ) - for ((matchedEntryFact, delta) in deltas) { - // todo: remove this check? - if (!mappedSummaryFact.contains(matchedEntryFact)) continue - - for (mappedSummaryInitialFact in mappedSummaryInitial) { - val precondition = mappedSummaryInitialFact - .concat(delta) - .replaceExclusions(callerFact.exclusions) - - resolvedCallSummaries.addCallSummaryEntry( - currentTraceEdge = currentEdge, - precondition = precondition, - preconditionDelta = delta, - callee = callee, - summaryFinalFact = matchedEntryFact, - summaryEdge = summaryEdge, - ) + for ((matchedEntryFact, delta) in deltas) { + // todo: remove this check? + if (!mappedSummaryFact.contains(matchedEntryFact)) continue + + for (mappedSummaryInitialFact in mappedSummaryInitial) { + val precondition = mappedSummaryInitialFact + .concat(delta) + .replaceExclusions(callerFact.exclusions) + + resolvedCallSummaries.addCallSummaryEntry( + currentTraceEdge = currentEdge, + precondition = precondition, + preconditionDelta = delta, + callee = callee, + summaryFinalFact = matchedEntryFact, + summaryEdge = summaryEdge, + ) + } } } } @@ -1655,7 +1724,7 @@ class MethodTraceResolver( private fun MutableList.resolveCallSourceSummary( currentEdge: TraceEdge.SourceTraceEdge, callee: MethodEntryPoint, - startFact: CallPreconditionFact.CallToStart + startFact: MethodCallPrecondition.CallToStartResolved ) { val relevantSummaryEdges = manager.findZeroToFactSummaryEdges(callee, startFact.startFactBase) val applicableSummaryEdges = relevantSummaryEdges.filter { isApplicableExitToReturnEdge(it) } diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt index a72b68abb..b653d836d 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt @@ -20,6 +20,7 @@ import org.opentaint.dataflow.ap.ifds.analysis.MethodStartFlowFunction import org.opentaint.dataflow.ap.ifds.taint.ExternalMethodTracker import org.opentaint.dataflow.ap.ifds.taint.TaintAnalysisContext import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodStartPrecondition import org.opentaint.dataflow.go.GoCallExpr @@ -30,6 +31,7 @@ import org.opentaint.dataflow.go.graph.GoApplicationGraph import org.opentaint.dataflow.go.rules.GoTaintAnalysisContext import org.opentaint.dataflow.go.rules.GoTaintRulesProvider import org.opentaint.dataflow.go.trace.GoMethodCallPrecondition +import org.opentaint.dataflow.go.trace.GoMethodCallSummaryPreconditionHandler import org.opentaint.dataflow.go.trace.GoMethodSequentPrecondition import org.opentaint.dataflow.go.trace.GoMethodStartPrecondition import org.opentaint.dataflow.graph.MethodInstGraph @@ -158,6 +160,12 @@ class GoAnalysisManager( ) } + override fun getMethodCallSummaryPreconditionHandler( + apManager: ApManager, + analysisContext: MethodAnalysisContext, + statement: CommonInst + ): MethodCallSummaryPreconditionHandler = GoMethodCallSummaryPreconditionHandler + override fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoCallRuleBasedSummaryRewriter.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoCallRuleBasedSummaryRewriter.kt index f07eec3f5..56c79c02e 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoCallRuleBasedSummaryRewriter.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoCallRuleBasedSummaryRewriter.kt @@ -57,8 +57,9 @@ class GoCallRuleBasedSummaryRewriter( if (cleanRuleWithCond.condition.isFalse) continue - val positions = cleanRule.actionsAfter.filterIsInstance().mapTo(hashSetOf()) { it.pos } - result += UserRuleDefinedAction(cleanRule, positions, ruleInfo.relevantTaintMarks) + cleanRule.actionsAfter.filterIsInstance().forEach { action -> + result += UserRuleDefinedAction(cleanRule, setOf(action.pos), ruleInfo.relevantTaintMarks + action.mark) + } } result diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt index 06f33f17a..2d7c79d7c 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt @@ -3,6 +3,7 @@ package org.opentaint.dataflow.go.analysis import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.ExclusionSet import org.opentaint.dataflow.ap.ifds.FactTypeChecker +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -52,7 +53,7 @@ class GoMethodCallFlowFunction( } override fun propagateZeroToZero(): Set { - val result = mutableSetOf( + val result = mutableSetOf( CallToReturnZeroFact, CallToStartZeroFact, ) @@ -176,6 +177,7 @@ class GoMethodCallFlowFunction( override fun propagateUnresolvedCallFact( factAp: FinalFactAp, + startFactBase: AccessPathBase, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, addSideEffectRequirement: (FinalFactReader) -> Unit ) { @@ -234,6 +236,16 @@ class GoMethodCallFlowFunction( } } + override fun propagateSuccessCallFact( + factAp: FinalFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint, + addSideEffectRequirement: (FinalFactReader) -> Unit, + addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, + addCallToStart: (callerFact: FinalFactAp, startFactBase: AccessPathBase, TraceInfo?) -> Unit, + addUnchecked: (MethodCallFlowFunction.CallFact) -> Unit, + ) = addCallToStart(factAp, startFactBase, null) + private fun propagateDefault( factAp: FinalFactAp, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt index 0c7f63d37..f136e3105 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt @@ -1,6 +1,7 @@ package org.opentaint.dataflow.go.trace import org.opentaint.dataflow.ap.ifds.AccessPathBase +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.TaintMarkAccessor import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -8,9 +9,11 @@ import org.opentaint.dataflow.ap.ifds.taint.TaintAnalysisContext.RuleWithConditi import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact -import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact.CallFailurePreconditionFact +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallFailurePreconditionFact +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallSuccessPreconditionFact import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.PreconditionFactsForInitialFact import org.opentaint.dataflow.ap.ifds.trace.TaintRulePrecondition +import org.opentaint.dataflow.ap.ifds.trace.mkUnchanged import org.opentaint.dataflow.go.GoCallExpr import org.opentaint.dataflow.go.GoFlowFunctionUtils import org.opentaint.dataflow.go.GoFunctionSignature @@ -48,11 +51,11 @@ class GoMethodCallPrecondition( override fun mapExit2Return(fact: InitialFactAp): List = GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) - override fun factPrecondition(fact: InitialFactAp): List { - val result = mutableListOf() + override fun factPrecondition(fact: InitialFactAp): List> { + val result = mutableListOf>() result += preconditionForFact(fact)?.let { PreconditionFactsForInitialFact(fact, it) } - ?: CallPrecondition.Unchanged + ?: mkUnchanged() analysisContext.aliasAnalysis.forEachPossibleAliasAtStatement(statement, fact) { aliasedFact -> preconditionForFact(aliasedFact)?.let { @@ -77,16 +80,24 @@ class GoMethodCallPrecondition( val result = mutableListOf() if (startFactBase != AccessPathBase.Return) { - result += CallPreconditionFact.UnresolvedCallSkip + result += MethodCallPrecondition.UnresolvedCallSkip } factPassRulePrecondition(fact, startFactBase).mapTo(result) { - CallPreconditionFact.CallToReturnTaintRule(it) + MethodCallPrecondition.CallToReturnTaintRule(it) } return result } + override fun factPreconditionResolutionSuccess( + fact: InitialFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint + ): List = listOf( + MethodCallPrecondition.CallToStartResolved(fact, startFactBase, ep) + ) + private fun preconditionForFact(fact: InitialFactAp): List? { if (!factIsRelevantToMethodCall(statement, returnValue, callExpr, fact)) return null @@ -114,10 +125,10 @@ class GoMethodCallPrecondition( startBase: AccessPathBase, ) { factSourceRulePrecondition(fact, startBase).mapTo(this) { - CallPreconditionFact.CallToReturnTaintRule(it) + MethodCallPrecondition.CallToReturnTaintRule(it) } - this += CallPreconditionFact.CallToStart(fact, startBase) + this += MethodCallPrecondition.CallToStart(fact, startBase) } private fun factSourceRulePrecondition( diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt new file mode 100644 index 000000000..da3ce3247 --- /dev/null +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt @@ -0,0 +1,5 @@ +package org.opentaint.dataflow.go.trace + +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler + +object GoMethodCallSummaryPreconditionHandler : MethodCallSummaryPreconditionHandler diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt index cf928a62a..a811eb4c6 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt @@ -21,6 +21,7 @@ import org.opentaint.dataflow.ap.ifds.analysis.MethodStartFlowFunction import org.opentaint.dataflow.ap.ifds.taint.ExternalMethodTracker import org.opentaint.dataflow.ap.ifds.taint.TaintAnalysisContext import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodStartPrecondition import org.opentaint.dataflow.graph.MethodInstGraph @@ -36,6 +37,7 @@ import org.opentaint.dataflow.jvm.ap.ifds.jIRDowncast import org.opentaint.dataflow.jvm.ap.ifds.taint.JIRTaintAnalysisContext import org.opentaint.dataflow.jvm.ap.ifds.taint.TaintRulesProvider import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodCallPrecondition +import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodCallSummaryPreconditionHandler import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodSequentPrecondition import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodStartPrecondition import org.opentaint.dataflow.jvm.ifds.JIRUnitResolver @@ -236,6 +238,12 @@ class JIRAnalysisManager( } } + override fun getMethodCallSummaryPreconditionHandler( + apManager: ApManager, + analysisContext: MethodAnalysisContext, + statement: CommonInst + ): MethodCallSummaryPreconditionHandler = JIRMethodCallSummaryPreconditionHandler + override fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt index 5ee1493f3..32ff906ac 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt @@ -2,6 +2,7 @@ package org.opentaint.dataflow.jvm.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.ExclusionSet +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -12,6 +13,7 @@ import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFlowFunction.CallToRetu import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFlowFunction.CallToReturnZeroFact import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFlowFunction.CallToStartZeroFact import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFlowFunction.TraceInfo +import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFlowFunction.ZeroCallFact import org.opentaint.dataflow.configuration.jvm.TaintConfigurationItem import org.opentaint.dataflow.configuration.jvm.serialized.UserDefinedRuleInfo import org.opentaint.dataflow.jvm.ap.ifds.JIRCallResolver @@ -53,7 +55,7 @@ class JIRMethodCallFlowFunction( JIRMethodPositionBaseTypeResolver(callExpr.method.method) } - override fun propagateZeroToZero() = buildSet { + override fun propagateZeroToZero(): Set = buildSet { applySinkRules( factReader = null, markAfterAnyFieldResolver = null @@ -252,6 +254,7 @@ class JIRMethodCallFlowFunction( override fun propagateUnresolvedCallFact( factAp: FinalFactAp, + startFactBase: AccessPathBase, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, addSideEffectRequirement: (FinalFactReader) -> Unit ) { @@ -326,6 +329,16 @@ class JIRMethodCallFlowFunction( } } + override fun propagateSuccessCallFact( + factAp: FinalFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint, + addSideEffectRequirement: (FinalFactReader) -> Unit, + addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, + addCallToStart: (callerFact: FinalFactAp, startFactBase: AccessPathBase, TraceInfo?) -> Unit, + addUnchecked: (MethodCallFlowFunction.CallFact) -> Unit, + ) = addCallToStart(factAp, startFactBase, null) + private fun unresolvedCallDefaultFactPropagation( factAp: FinalFactAp, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallRuleBasedSummaryRewriter.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallRuleBasedSummaryRewriter.kt index 48db87b26..5c267c2d9 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallRuleBasedSummaryRewriter.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallRuleBasedSummaryRewriter.kt @@ -80,8 +80,9 @@ class JIRMethodCallRuleBasedSummaryRewriter( val simplifiedCondition = conditionRewriter.rewrite(cleanRule.condition) if (simplifiedCondition.isFalse) continue - val positions = cleanRule.actionsAfter.filterIsInstance().mapTo(hashSetOf()) { it.position } - indexRule(cleanRule, positions, ruleInfo.relevantTaintMarks) + cleanRule.actionsAfter.filterIsInstance().forEach { action -> + indexRule(cleanRule, setOf(action.position), ruleInfo.relevantTaintMarks + action.mark.name) + } } result diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt index c9b0f53a0..f3977b3a7 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt @@ -1,17 +1,20 @@ package org.opentaint.dataflow.jvm.ap.ifds.trace import org.opentaint.dataflow.ap.ifds.AccessPathBase +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.TaintMarkAccessor import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFactMapper import org.opentaint.dataflow.ap.ifds.taint.TaintAnalysisContext.RuleWithCondition import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallFailurePreconditionFact import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact -import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact.CallFailurePreconditionFact +import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallSuccessPreconditionFact import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.PreconditionFactsForInitialFact import org.opentaint.dataflow.ap.ifds.trace.TaintRulePrecondition +import org.opentaint.dataflow.ap.ifds.trace.mkUnchanged import org.opentaint.dataflow.configuration.jvm.TaintMethodSource import org.opentaint.dataflow.configuration.jvm.TaintPassThrough import org.opentaint.dataflow.jvm.ap.ifds.JIRMethodCallFactMapper @@ -44,11 +47,11 @@ class JIRMethodCallPrecondition( private val taintCtx get() = analysisContext.taint - override fun factPrecondition(fact: InitialFactAp): List { - val results = mutableListOf() + override fun factPrecondition(fact: InitialFactAp): List> { + val results = mutableListOf>() results += preconditionForFact(fact)?.let { PreconditionFactsForInitialFact(fact, it) } - ?: CallPrecondition.Unchanged + ?: mkUnchanged() analysisContext.aliasAnalysis?.forEachPossibleAliasAtStatement(statement, fact) { aliasedFact -> preconditionForFact(aliasedFact)?.let { results += PreconditionFactsForInitialFact(aliasedFact, it) } @@ -64,7 +67,7 @@ class JIRMethodCallPrecondition( val preconditions = mutableListOf() if (startFactBase != AccessPathBase.Return) { - preconditions += CallPreconditionFact.UnresolvedCallSkip + preconditions += MethodCallPrecondition.UnresolvedCallSkip } preconditions += rulePreconditionForFactResolutionFailure(fact, startFactBase) @@ -72,6 +75,14 @@ class JIRMethodCallPrecondition( return preconditions } + override fun factPreconditionResolutionSuccess( + fact: InitialFactAp, + startFactBase: AccessPathBase, + ep: MethodEntryPoint + ): List = listOf( + MethodCallPrecondition.CallToStartResolved(fact, startFactBase, ep) + ) + private fun preconditionForFact(fact: InitialFactAp): List? { if (!factIsRelevantToMethodCall(statement, returnValue, callExpr, fact)) { return null @@ -103,9 +114,9 @@ class JIRMethodCallPrecondition( val rulePreconditions = mutableListOf() rulePreconditions.factSourceRulePrecondition(fact, startBase) - rulePreconditions.mapTo(this) { CallPreconditionFact.CallToReturnTaintRule(it) } + rulePreconditions.mapTo(this) { MethodCallPrecondition.CallToReturnTaintRule(it) } - this += CallPreconditionFact.CallToStart(fact, startBase) + this += MethodCallPrecondition.CallToStart(fact, startBase) } private fun rulePreconditionForFactResolutionFailure( @@ -115,7 +126,7 @@ class JIRMethodCallPrecondition( val rulePreconditions = mutableListOf() rulePreconditions.factPassRulePrecondition(fact, startBase) - return rulePreconditions.map { CallPreconditionFact.CallToReturnTaintRule(it) } + return rulePreconditions.map { MethodCallPrecondition.CallToReturnTaintRule(it) } } private fun MutableList.factSourceRulePrecondition( diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt new file mode 100644 index 000000000..9ecef9830 --- /dev/null +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt @@ -0,0 +1,5 @@ +package org.opentaint.dataflow.jvm.ap.ifds.trace + +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler + +object JIRMethodCallSummaryPreconditionHandler : MethodCallSummaryPreconditionHandler diff --git a/core/opentaint-java-querylang/src/main/kotlin/org/opentaint/semgrep/pattern/conversion/taint/TaintRuleGenerationCtx.kt b/core/opentaint-java-querylang/src/main/kotlin/org/opentaint/semgrep/pattern/conversion/taint/TaintRuleGenerationCtx.kt index c13ae60c7..ec70f7fc5 100644 --- a/core/opentaint-java-querylang/src/main/kotlin/org/opentaint/semgrep/pattern/conversion/taint/TaintRuleGenerationCtx.kt +++ b/core/opentaint-java-querylang/src/main/kotlin/org/opentaint/semgrep/pattern/conversion/taint/TaintRuleGenerationCtx.kt @@ -152,8 +152,7 @@ data class TaintRuleGenerationCtx( fun edgeRuleInfo(edge: TaintRuleEdge): UserRuleFromSemgrepInfo { val relevantTaintMarks = hashSetOf() relevantTaintMarks += usedTaintMarks(edge.stateFrom) - relevantTaintMarks += usedTaintMarks(edge.stateTo) - if (edge.checkGlobalState || edge.stateTo in globalStateAssignStates) { + if (edge.checkGlobalState) { relevantTaintMarks += globalStateMarkName(edge.stateTo) } From 57c2422212b453dfe0b56f6cb6796fac5f9a07cf Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Tue, 4 Aug 2026 17:57:22 +0300 Subject: [PATCH 02/12] Add `prepareZeroToFactSummary` --- .../org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt | 10 +++++++++- .../ap/ifds/analysis/MethodCallSummaryHandler.kt | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index 4be8a15c2..901b7473c 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -1053,11 +1053,19 @@ class NormalMethodAnalyzer( ) { summaryEdgesHandled++ - val applicableSummaries = methodSummaries.filter { isApplicableExitToReturnEdge(it) } val handler = analysisManager.getMethodCallSummaryHandler( apManager, analysisContext, currentEdge.statement ) + val applicableSummaries = methodSummaries.flatMap { summary -> + if (!isApplicableExitToReturnEdge(summary)) return@flatMap emptyList() + + when (summary) { + is ZeroToZero -> listOf(summary) + is ZeroToFact -> handler.prepareZeroToFactSummary(summary) + } + } + for (methodSummary in applicableSummaries) { if (!cancellation.isActive()) return diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt index 4aa86070d..4568b2aef 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt @@ -33,6 +33,8 @@ interface MethodCallSummaryHandler { } } + fun prepareZeroToFactSummary(summaryEdge: Edge.ZeroToFact): List = listOf(summaryEdge) + fun handleZeroToFact( currentFactAp: FinalFactAp, summaryEffect: EdgeRefinement, From 29c39a988d3f4a0b6f60af3ce72f71b8802c460b Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Wed, 5 Aug 2026 16:09:10 +0300 Subject: [PATCH 03/12] Use MethodWithContext in success call resolution --- .../dataflow/ap/ifds/MethodAnalyzer.kt | 63 +++++++------------ .../ifds/analysis/MethodCallFlowFunction.kt | 26 ++++---- .../ap/ifds/trace/MethodCallPrecondition.kt | 6 +- .../ap/ifds/trace/MethodTraceResolver.kt | 34 +++++----- .../go/analysis/GoMethodCallFlowFunction.kt | 4 +- .../go/trace/GoMethodCallPrecondition.kt | 6 +- .../analysis/JIRMethodCallFlowFunction.kt | 4 +- .../ifds/trace/JIRMethodCallPrecondition.kt | 6 +- 8 files changed, 68 insertions(+), 81 deletions(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index 901b7473c..b96b9933f 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -114,8 +114,6 @@ interface MethodAnalyzer { fun handleResolvedMethodCall(method: MethodWithContext, handler: MethodCallHandler) - fun handleResolvedMethodCall(entryPoint: MethodEntryPoint, handler: MethodCallHandler) - fun handleMethodCallResolutionFailure( callExpr: CommonCallExpr, handler: MethodCallResolutionFailureHandler @@ -543,17 +541,17 @@ class NormalMethodAnalyzer( callExpr: CommonCallExpr, edge: ZeroInitialEdge, fact: MethodCallFlowFunction.ZeroCallSuccessFact, - ep: MethodEntryPoint, + method: MethodWithContext, ) { when (fact) { is MethodCallFlowFunction.CallToStartZeroFact -> { val callerEdge = ZeroToZero(methodEntryPoint, edge.statement) - runner.subscribeOnMethodSummaries(callerEdge, ep) + handleMethodCall(method) { runner.subscribeOnMethodSummaries(callerEdge, it) } } is MethodCallFlowFunction.CallToStartZFact -> { val callerEdge = ZeroToFact(methodEntryPoint, edge.statement, fact.callerFactAp) - runner.subscribeOnMethodSummaries(callerEdge, ep, fact.startFactBase) + handleMethodCall(method) { runner.subscribeOnMethodSummaries(callerEdge, it, fact.startFactBase) } } is MethodCallFlowFunction.CallToReturnFFact, @@ -567,13 +565,13 @@ class NormalMethodAnalyzer( callExpr: CommonCallExpr, edge: FactToFact, fact: MethodCallFlowFunction.FactCallSuccessFact, - ep: MethodEntryPoint, + method: MethodWithContext, ) { when (fact) { is MethodCallFlowFunction.CallToStartFFact -> { val callerEdge = FactToFact(methodEntryPoint, fact.initialFactAp, edge.statement, fact.callerFactAp) handleInputFactChange(edge.initialFactAp, callerEdge.initialFactAp) - runner.subscribeOnMethodSummaries(callerEdge, ep, fact.startFactBase) + handleMethodCall(method) { runner.subscribeOnMethodSummaries(callerEdge, it, fact.startFactBase) } } is MethodCallFlowFunction.CallToReturnFFact, @@ -588,12 +586,12 @@ class NormalMethodAnalyzer( callExpr: CommonCallExpr, edge: NDFactToFact, fact: MethodCallFlowFunction.NDFactCallSuccessFact, - ep: MethodEntryPoint, + method: MethodWithContext, ) { when (fact) { is MethodCallFlowFunction.CallToStartNDFFact -> { val callerEdge = NDFactToFact(methodEntryPoint, fact.initialFacts, edge.statement, fact.callerFactAp) - runner.subscribeOnMethodSummaries(callerEdge, ep, fact.startFactBase) + handleMethodCall(method) { runner.subscribeOnMethodSummaries(callerEdge, it, fact.startFactBase) } } is MethodCallFlowFunction.CallToReturnZFact, @@ -807,16 +805,6 @@ class NormalMethodAnalyzer( } override fun handleResolvedMethodCall(method: MethodWithContext, handler: MethodCallHandler) { - for (ep in methodEntryPoints(method)) { - handleMethodCall(handler, ep) - } - } - - override fun handleResolvedMethodCall(entryPoint: MethodEntryPoint, handler: MethodCallHandler) { - handleMethodCall(handler, entryPoint) - } - - private fun handleMethodCall(handler: MethodCallHandler, ep: MethodEntryPoint) { val statement = handler.currentEdge.statement val callExpr = analysisManager.getCallExpr(statement) ?: error("Expected call expression") val returnValue: CommonValue? = (statement as? CommonAssignInst)?.lhv @@ -828,36 +816,42 @@ class NormalMethodAnalyzer( statement, generateTrace = false, ) - - return when (handler) { + + when (handler) { is MethodCallHandler.ZeroToZeroHandler -> { - flowFunction.propagateZeroToZeroResolutionSuccess(ep).forEach { - propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, ep) + flowFunction.propagateZeroToZeroResolutionSuccess(method).forEach { + propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, method) } } is MethodCallHandler.ZeroToFactHandler -> { - flowFunction.propagateZeroToFactResolutionSuccess(handler.currentEdge.factAp, handler.startFactBase, ep).forEach { - propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, ep) + flowFunction.propagateZeroToFactResolutionSuccess(handler.currentEdge.factAp, handler.startFactBase, method).forEach { + propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, method) } } is MethodCallHandler.FactToFactHandler -> { val edge = handler.currentEdge - flowFunction.propagateFactToFactResolutionSuccess(edge.initialFactAp, edge.factAp, handler.startFactBase, ep).forEach { - propagateFactCallSuccessFact(callExpr, edge, it, ep) + flowFunction.propagateFactToFactResolutionSuccess(edge.initialFactAp, edge.factAp, handler.startFactBase, method).forEach { + propagateFactCallSuccessFact(callExpr, edge, it, method) } } is MethodCallHandler.NDFactToFactHandler -> { val edge = handler.currentEdge - flowFunction.propagateNDFactToFactResolutionSuccess(edge.initialFacts, edge.factAp, handler.startFactBase, ep).forEach { - propagateNDFactCallSuccessFact(callExpr, edge, it, ep) + flowFunction.propagateNDFactToFactResolutionSuccess(edge.initialFacts, edge.factAp, handler.startFactBase, method).forEach { + propagateNDFactCallSuccessFact(callExpr, edge, it, method) } } } } + private inline fun handleMethodCall(method: MethodWithContext, subscribeOnMethodSummaries: (MethodEntryPoint) -> Unit) { + for (ep in methodEntryPoints(method)) { + subscribeOnMethodSummaries(ep) + } + } + override fun handleMethodCallResolutionFailure( callExpr: CommonCallExpr, handler: MethodCallResolutionFailureHandler @@ -1650,10 +1644,6 @@ class EmptyMethodAnalyzer( error("Empty method should not method resolution results") } - override fun handleResolvedMethodCall(entryPoint: MethodEntryPoint, handler: MethodCallHandler) { - error("Empty method should not method resolution results") - } - override fun handleMethodCallResolutionFailure(callExpr: CommonCallExpr, handler: MethodCallResolutionFailureHandler) { error("Empty method should not method resolution results") } @@ -1912,13 +1902,6 @@ class TimedMethodAnalyzer( base.handleResolvedMethodCall(method, handler) } - override fun handleResolvedMethodCall(entryPoint: MethodEntryPoint, handler: MethodCallHandler) = timeOperation( - operation = "handleResolvedMethodCall(entryPoint)", - category = OpCategory.CALL, - ) { - base.handleResolvedMethodCall(entryPoint, handler) - } - override fun handleMethodCallResolutionFailure( callExpr: CommonCallExpr, handler: MethodCallResolutionFailureHandler, diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt index 83e6c1075..d7b6d8a82 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallFlowFunction.kt @@ -2,7 +2,7 @@ package org.opentaint.dataflow.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.ExclusionSet -import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.MethodWithContext import org.opentaint.dataflow.ap.ifds.SideEffectKind import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -100,10 +100,10 @@ interface MethodCallFlowFunction { fun propagateFactToFactResolutionFailure(initialFactAp: InitialFactAp, currentFactAp: FinalFactAp, startFactBase: AccessPathBase): Set fun propagateNDFactToFactResolutionFailure(initialFacts: Set, currentFactAp: FinalFactAp, startFactBase: AccessPathBase): Set - fun propagateZeroToZeroResolutionSuccess(ep: MethodEntryPoint): Set - fun propagateZeroToFactResolutionSuccess(currentFactAp: FinalFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): Set - fun propagateFactToFactResolutionSuccess(initialFactAp: InitialFactAp, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): Set - fun propagateNDFactToFactResolutionSuccess(initialFacts: Set, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): Set + fun propagateZeroToZeroResolutionSuccess(method: MethodWithContext): Set + fun propagateZeroToFactResolutionSuccess(currentFactAp: FinalFactAp, startFactBase: AccessPathBase, method: MethodWithContext): Set + fun propagateFactToFactResolutionSuccess(initialFactAp: InitialFactAp, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, method: MethodWithContext): Set + fun propagateNDFactToFactResolutionSuccess(initialFacts: Set, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, method: MethodWithContext): Set interface Default : MethodCallFlowFunction { override fun propagateZeroToFact(currentFactAp: FinalFactAp) = buildSet { @@ -249,18 +249,18 @@ interface MethodCallFlowFunction { ) } - override fun propagateZeroToZeroResolutionSuccess(ep: MethodEntryPoint): Set = + override fun propagateZeroToZeroResolutionSuccess(method: MethodWithContext): Set = setOf(CallToStartZeroFact) override fun propagateZeroToFactResolutionSuccess( currentFactAp: FinalFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint, + method: MethodWithContext, ): Set = buildSet { propagateSuccessCallFact( factAp = currentFactAp, startFactBase = startFactBase, - ep = ep, + method = method, addSideEffectRequirement = { factReader -> check(!factReader.hasRefinement) { "Can't refine Zero fact" } }, @@ -282,12 +282,12 @@ interface MethodCallFlowFunction { initialFactAp: InitialFactAp, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint, + method: MethodWithContext, ): Set = buildSet { propagateSuccessCallFact( factAp = currentFactAp, startFactBase = startFactBase, - ep = ep, + method = method, addSideEffectRequirement = { factReader -> this += SideEffectRequirement(factReader.refineFact(initialFactAp.replaceExclusions(ExclusionSet.Empty))) }, @@ -312,12 +312,12 @@ interface MethodCallFlowFunction { initialFacts: Set, currentFactAp: FinalFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint, + method: MethodWithContext, ): Set = buildSet { propagateSuccessCallFact( factAp = currentFactAp, startFactBase = startFactBase, - ep = ep, + method = method, addSideEffectRequirement = { factReader -> check(!factReader.hasRefinement) { "Can't refine NDF2F edge" } }, @@ -356,7 +356,7 @@ interface MethodCallFlowFunction { fun propagateSuccessCallFact( factAp: FinalFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint, + method: MethodWithContext, addSideEffectRequirement: (FinalFactReader) -> Unit, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, addCallToStart: (callerFact: FinalFactAp, startFactBase: AccessPathBase, TraceInfo?) -> Unit, diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt index 0c31d4125..2a0d4f688 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt @@ -2,7 +2,7 @@ package org.opentaint.dataflow.ap.ifds.trace import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.MethodAnalyzerEdges -import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.MethodWithContext import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -32,11 +32,11 @@ interface MethodCallPrecondition { object UnresolvedCallSkip : CallPreconditionFact, CallFailurePreconditionFact data class CallToReturnTaintRule(val precondition: TaintRulePrecondition) : CallPreconditionFact, CallFailurePreconditionFact, CallSuccessPreconditionFact data class CallToStart(val callerFact: InitialFactAp, val startFactBase: AccessPathBase) : CallPreconditionFact - data class CallToStartResolved(val callerFact: InitialFactAp, val startFactBase: AccessPathBase, val method: MethodEntryPoint): CallSuccessPreconditionFact + data class CallToStartResolved(val callerFact: InitialFactAp, val startFactBase: AccessPathBase, val method: MethodWithContext): CallSuccessPreconditionFact fun factPrecondition(fact: InitialFactAp): List> fun factPreconditionResolutionFailure(fact: InitialFactAp, startFactBase: AccessPathBase): List - fun factPreconditionResolutionSuccess(fact: InitialFactAp, startFactBase: AccessPathBase, ep: MethodEntryPoint): List + fun factPreconditionResolutionSuccess(fact: InitialFactAp, startFactBase: AccessPathBase, method: MethodWithContext): List data class PassRuleConditionFacts(val facts: List) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt index 058ff7bdf..645498513 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt @@ -1135,7 +1135,8 @@ class MethodTraceResolver( callActions.forEachCartesianProduct { actions -> resolveCall2StartActions(actions, preconditionFunction, callees) { boundActions -> boundActions.forEachCartesianProduct { resolvedActions -> - mergeCallActions(resolvedActions)?.let { body(it) } + val mergedActions = mergeCallActions(resolvedActions) + mergedActions.forEach(body) } } } @@ -1163,10 +1164,8 @@ class MethodTraceResolver( } is MethodCallResolutionResult.ResolvedMethod -> { - methodEntryPoints(callee.method).forEach { - val expandedActions = resolveCall2StartSuccess(actions, preconditionFunction, it) - process(expandedActions) - } + val expandedActions = resolveCall2StartSuccess(actions, preconditionFunction, callee.method) + process(expandedActions) } } } @@ -1175,9 +1174,9 @@ class MethodTraceResolver( private fun resolveCall2StartSuccess( actions: Array>, preconditionFunction: MethodCallPrecondition, - ep: MethodEntryPoint + method: MethodWithContext ): List>> = resolveCall2StartActions(actions) { callerFact, base -> - preconditionFunction.factPreconditionResolutionSuccess(callerFact, base, ep) + preconditionFunction.factPreconditionResolutionSuccess(callerFact, base, method) } private fun resolveCall2StartFailure( @@ -1246,7 +1245,7 @@ class MethodTraceResolver( private fun mergeCallActions( aouGroup: Array>, - ): PartialCallEdgeCombination? { + ): List { val unchanged = hashSetOf() val rules = hashSetOf() val summary = hashSetOf() @@ -1270,23 +1269,28 @@ class MethodTraceResolver( if (summary.isEmpty()) { if (unresolvedSkips.isEmpty()) { - return PartialCallEdgeCombination(unchanged, primary = null, mergedRules) + return listOf(PartialCallEdgeCombination(unchanged, primary = null, mergedRules)) } val skippedEdges = unresolvedSkips.mapTo(hashSetOf()) { it.currentEdge } val primary = MergedPrimaryUnresolvedCallSkip(UnresolvedCallSkip(skippedEdges, skippedEdges)) - return PartialCallEdgeCombination(unchanged, primary, mergedRules) + return listOf(PartialCallEdgeCombination(unchanged, primary, mergedRules)) } if (unresolvedSkips.isNotEmpty()) { // note: we have a summary (i.e. call resolved) and an unresolved call - return null + return emptyList() } - // all summaries have the same entry-point - val ep = summary.first().call2Start.method - val primary = MergedPrimaryCall2StartAction(ep, summary) - return PartialCallEdgeCombination(unchanged, primary, mergedRules) + // all summaries have the same method + val method = summary.first().call2Start.method + val result = mutableListOf() + for (ep in methodEntryPoints(method)) { + val primary = MergedPrimaryCall2StartAction(ep, summary) + result += PartialCallEdgeCombination(unchanged, primary, mergedRules) + } + + return result } private fun mergeCallRules(callRules: HashSet): Set { diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt index 2d7c79d7c..efd37f5de 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallFlowFunction.kt @@ -3,7 +3,7 @@ package org.opentaint.dataflow.go.analysis import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.ExclusionSet import org.opentaint.dataflow.ap.ifds.FactTypeChecker -import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.MethodWithContext import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -239,7 +239,7 @@ class GoMethodCallFlowFunction( override fun propagateSuccessCallFact( factAp: FinalFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint, + method: MethodWithContext, addSideEffectRequirement: (FinalFactReader) -> Unit, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, addCallToStart: (callerFact: FinalFactAp, startFactBase: AccessPathBase, TraceInfo?) -> Unit, diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt index f136e3105..1dfc6d48e 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt @@ -1,7 +1,7 @@ package org.opentaint.dataflow.go.trace import org.opentaint.dataflow.ap.ifds.AccessPathBase -import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.MethodWithContext import org.opentaint.dataflow.ap.ifds.TaintMarkAccessor import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -93,9 +93,9 @@ class GoMethodCallPrecondition( override fun factPreconditionResolutionSuccess( fact: InitialFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint + method: MethodWithContext ): List = listOf( - MethodCallPrecondition.CallToStartResolved(fact, startFactBase, ep) + MethodCallPrecondition.CallToStartResolved(fact, startFactBase, method) ) private fun preconditionForFact(fact: InitialFactAp): List? { diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt index 32ff906ac..edf84c819 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallFlowFunction.kt @@ -2,7 +2,7 @@ package org.opentaint.dataflow.jvm.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.AccessPathBase import org.opentaint.dataflow.ap.ifds.ExclusionSet -import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.MethodWithContext import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -332,7 +332,7 @@ class JIRMethodCallFlowFunction( override fun propagateSuccessCallFact( factAp: FinalFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint, + method: MethodWithContext, addSideEffectRequirement: (FinalFactReader) -> Unit, addCallToReturn: (FinalFactReader, FinalFactAp, TraceInfo?) -> Unit, addCallToStart: (callerFact: FinalFactAp, startFactBase: AccessPathBase, TraceInfo?) -> Unit, diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt index f3977b3a7..6b365878f 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt @@ -1,7 +1,7 @@ package org.opentaint.dataflow.jvm.ap.ifds.trace import org.opentaint.dataflow.ap.ifds.AccessPathBase -import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.MethodWithContext import org.opentaint.dataflow.ap.ifds.TaintMarkAccessor import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.InitialFactAp @@ -78,9 +78,9 @@ class JIRMethodCallPrecondition( override fun factPreconditionResolutionSuccess( fact: InitialFactAp, startFactBase: AccessPathBase, - ep: MethodEntryPoint + method: MethodWithContext ): List = listOf( - MethodCallPrecondition.CallToStartResolved(fact, startFactBase, ep) + MethodCallPrecondition.CallToStartResolved(fact, startFactBase, method) ) private fun preconditionForFact(fact: InitialFactAp): List? { From f0517dd8155ef338cb5f71aa27f4ffa38da38d9f Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Wed, 5 Aug 2026 17:19:27 +0300 Subject: [PATCH 04/12] Add ep to SummaryEdge --- .../opentaint/dataflow/ap/ifds/MethodAnalyzer.kt | 4 ++-- .../ap/ifds/analysis/MethodCallSummaryHandler.kt | 15 +++++++++++++-- .../ap/ifds/trace/MethodForwardTraceResolver.kt | 4 +++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index b96b9933f..fd2e71908 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -1450,8 +1450,8 @@ class NormalMethodAnalyzer( } } - private fun FactToFact.summaryEdge() = SummaryEdge.F2F(initialFactAp, factAp) - private fun NDFactToFact.summaryEdge() = SummaryEdge.NdF2F(initialFacts, factAp) + private fun FactToFact.summaryEdge() = SummaryEdge.F2F(this.methodEntryPoint, initialFactAp, factAp) + private fun NDFactToFact.summaryEdge() = SummaryEdge.NdF2F(this.methodEntryPoint, initialFacts, factAp) override fun cleanup() { methodEntryPointsCache = hashMapOf() diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt index 4568b2aef..04a1b606e 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt @@ -3,6 +3,7 @@ package org.opentaint.dataflow.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.Edge import org.opentaint.dataflow.ap.ifds.ExclusionSet import org.opentaint.dataflow.ap.ifds.FactTypeChecker +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils.EdgeRefinement import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils.SummaryEdgeApplication import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils.SummaryEdgeApplication.SummaryApRefinement @@ -16,10 +17,20 @@ interface MethodCallSummaryHandler { val factTypeChecker: FactTypeChecker sealed interface SummaryEdge { + val methodEntryPoint: MethodEntryPoint val final: FinalFactAp - data class F2F(val initial: InitialFactAp, override val final: FinalFactAp) : SummaryEdge - data class NdF2F(val initial: Set, override val final: FinalFactAp) : SummaryEdge + data class F2F( + override val methodEntryPoint: MethodEntryPoint, + val initial: InitialFactAp, + override val final: FinalFactAp, + ) : SummaryEdge + + data class NdF2F( + override val methodEntryPoint: MethodEntryPoint, + val initial: Set, + override val final: FinalFactAp, + ) : SummaryEdge } fun mapMethodExitToReturnFlowFact(fact: FinalFactAp): List diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt index 0044b79e4..7f3c0b31d 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt @@ -307,7 +307,9 @@ class MethodForwardTraceResolver( for (summaryEdgeEffect in summaryEdgeEffects) { for (methodSummary in summaryEdges) { - val summaryEdge = SummaryEdge.F2F(methodSummary.initialFactAp, methodSummary.factAp) + val summaryEdge = SummaryEdge.F2F( + methodSummary.methodEntryPoint, methodSummary.initialFactAp, methodSummary.factAp + ) val sf = handleSummaryEdge(callerFact, summaryEdgeEffect, summaryEdge) handleSequentFact(currentEdge, sf) summaryApplied = true From cc00c76a7303b0d275c24f1ca041bc65f76c284d Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Tue, 11 Aug 2026 15:23:14 +0300 Subject: [PATCH 05/12] Refactor summary application --- .../dataflow/ap/ifds/MethodAnalyzer.kt | 68 +++++++----------- .../ap/ifds/analysis/AnalysisManager.kt | 7 -- .../ap/ifds/analysis/MethodAnalysisContext.kt | 3 - .../ifds/analysis/MethodCallSummaryHandler.kt | 69 +++++++++++++------ .../MethodSideEffectSummaryHandler.kt | 4 ++ .../MethodCallSummaryPreconditionHandler.kt | 7 -- .../ifds/trace/MethodForwardTraceResolver.kt | 11 ++- .../ap/ifds/trace/MethodTraceResolver.kt | 54 +++++++-------- .../dataflow/go/analysis/GoAnalysisManager.kt | 10 +-- .../go/analysis/GoMethodAnalysisContext.kt | 5 -- .../go/analysis/GoMethodCallSummaryHandler.kt | 21 ++++-- .../go/analysis/GoMethodSideEffectHandler.kt | 12 +++- .../GoMethodCallSummaryPreconditionHandler.kt | 5 -- .../ap/ifds/analysis/JIRAnalysisManager.kt | 10 +-- .../ifds/analysis/JIRMethodAnalysisContext.kt | 5 -- .../analysis/JIRMethodCallSummaryHandler.kt | 20 ++++-- .../analysis/JIRMethodSideEffectHandler.kt | 12 +++- .../ifds/trace/JIRMethodCallPrecondition.kt | 5 +- ...JIRMethodCallSummaryPreconditionHandler.kt | 5 -- 19 files changed, 157 insertions(+), 176 deletions(-) delete mode 100644 core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt delete mode 100644 core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt delete mode 100644 core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index fd2e71908..63675fd6a 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -962,11 +962,12 @@ class NormalMethodAnalyzer( runner ) + val summariesToApply = sideEffectSummaries.flatMap { handler.prepareSideEffectSummary(it) } + applyMethodSideEffectSummaries( currentEdge = sub.currentEdge, currentEdgeFactAp = sub.currentEdge.factAp, - methodInitialFactBase = sub.methodInitialFactBase, - sideEffectSummaries = sideEffectSummaries, + sideEffectSummaries = summariesToApply, handleSideEffect = handler::handleZeroToFact ) } @@ -985,11 +986,12 @@ class NormalMethodAnalyzer( runner, ) + val summariesToApply = sideEffectSummaries.flatMap { handler.prepareSideEffectSummary(it) } + applyMethodSideEffectSummaries( currentEdge = sub.currentEdge, currentEdgeFactAp = sub.currentEdge.factAp, - methodInitialFactBase = sub.methodInitialFactBase, - sideEffectSummaries = sideEffectSummaries, + sideEffectSummaries = summariesToApply, ) { currentFactAp, summaryEffect, kind -> handler.handleFactToFact(sub.currentEdge.initialFactAp, currentFactAp, summaryEffect, kind) } @@ -1091,7 +1093,6 @@ class NormalMethodAnalyzer( applyMethodSummaries( currentEdge = sub.currentEdge, currentEdgeFactAp = sub.currentEdge.factAp, - methodInitialFactBase = sub.methodInitialFactBase, methodSummaries = summariesToApply, handleSummaryEdge = handler::handleZeroToFact ) @@ -1104,7 +1105,7 @@ class NormalMethodAnalyzer( ) { handleMethodNDSummariesSub( summarySubs, methodSummaries, - { currentEdge }, { currentEdge.factAp }, { methodInitialFactBase } + { currentEdge }, { currentEdge.factAp } ) } @@ -1128,7 +1129,6 @@ class NormalMethodAnalyzer( applyMethodSummaries( currentEdge = sub.currentEdge, currentEdgeFactAp = sub.currentEdge.factAp, - methodInitialFactBase = sub.methodInitialFactBase, methodSummaries = summariesToApply, handleSummaryEdge = { currentFactAp: FinalFactAp, summaryEffect: SummaryEdgeApplication, summaryEdge: SummaryEdge -> handler.handleFactToFact(sub.currentEdge.initialFactAp, currentFactAp, summaryEffect, summaryEdge) @@ -1143,7 +1143,7 @@ class NormalMethodAnalyzer( ) { handleMethodNDSummariesSub( summarySubs, methodSummaries, - { currentEdge }, { currentEdge.factAp }, { methodInitialFactBase } + { currentEdge }, { currentEdge.factAp } ) } @@ -1167,7 +1167,6 @@ class NormalMethodAnalyzer( applyMethodSummaries( currentEdge = sub.currentEdge, currentEdgeFactAp = sub.currentEdge.factAp, - methodInitialFactBase = sub.methodInitialFactBase, methodSummaries = summariesToApply, handleSummaryEdge = { currentFactAp: FinalFactAp, summaryEffect: SummaryEdgeApplication, summaryEdge: SummaryEdge -> handler.handleNDFactToFact(sub.currentEdge.initialFacts, currentFactAp, summaryEffect, summaryEdge) @@ -1182,21 +1181,19 @@ class NormalMethodAnalyzer( ) { handleMethodNDSummariesSub( summarySubs, methodSummaries, - { currentEdge }, { currentEdge.factAp }, { methodInitialFactBase } + { currentEdge }, { currentEdge.factAp } ) } private fun applyMethodSummaries( currentEdge: Edge, currentEdgeFactAp: FinalFactAp, - methodInitialFactBase: AccessPathBase, methodSummaries: List, handleSummaryEdge: (currentFactAp: FinalFactAp, summaryEffect: SummaryEdgeApplication, summaryEdge: SummaryEdge) -> Set ) { applyMethodAnySummaries( currentEdge, currentEdgeFactAp, - methodInitialFactBase, methodSummaries, { it.initialFactAp } ) { currentFactAp, summaryEdgeEffect, methodSummary -> @@ -1207,14 +1204,12 @@ class NormalMethodAnalyzer( private fun applyMethodSideEffectSummaries( currentEdge: Edge, currentEdgeFactAp: FinalFactAp, - methodInitialFactBase: AccessPathBase, sideEffectSummaries: List, handleSideEffect: (currentFactAp: FinalFactAp, summaryEffect: SummaryEdgeApplication, kind: SideEffectKind) -> Set ) { applyMethodAnySummaries( currentEdge, currentEdgeFactAp, - methodInitialFactBase, sideEffectSummaries, { it.initialFactAp } ) { currentFactAp, summaryEdgeEffect, methodSummary -> @@ -1225,19 +1220,16 @@ class NormalMethodAnalyzer( private inline fun applyMethodAnySummaries( currentEdge: Edge, currentEdgeFactAp: FinalFactAp, - methodInitialFactBase: AccessPathBase, methodSummaries: List, getSummaryInitialFact: (S) -> InitialFactAp, handleSummary: (currentFactAp: FinalFactAp, summaryEffect: SummaryEdgeApplication, S) -> Set ) { - val methodInitialFact = currentEdgeFactAp.rebase(methodInitialFactBase) - val summaries = methodSummaries.groupByTo(hashMapOf()) { getSummaryInitialFact(it) } for ((summaryInitialFact, summaryEdges) in summaries) { if (!cancellation.isActive()) return val summaryEdgeEffects = MethodSummaryEdgeApplicationUtils.tryApplySummaryEdge( - methodInitialFact, summaryInitialFact + currentEdgeFactAp, summaryInitialFact ) for (summaryEdgeEffect in summaryEdgeEffects) { @@ -1256,7 +1248,6 @@ class NormalMethodAnalyzer( methodSummaries: List, subEdge: Sub.() -> Edge, subFact: Sub.() -> FinalFactAp, - subInitialFactBase: Sub.() -> AccessPathBase, ) { summaryEdgesHandled++ @@ -1277,7 +1268,6 @@ class NormalMethodAnalyzer( summaryHandler = handler, currentEdge = currentEdge, currentEdgeFactAp = sub.subFact(), - methodInitialFactBase = sub.subInitialFactBase(), methodSummaries = summariesToApply, ) } @@ -1287,22 +1277,19 @@ class NormalMethodAnalyzer( summaryHandler: MethodCallSummaryHandler, currentEdge: Edge, currentEdgeFactAp: FinalFactAp, - methodInitialFactBase: AccessPathBase, - methodSummaries: List, + methodSummaries: List, ) { - val methodInitialFact = currentEdgeFactAp.rebase(methodInitialFactBase) - nextSummary@for (summaryEdge in methodSummaries) { if (!cancellation.isActive()) return val requiredFacts = mutableListOf() - for (summaryInitialFact in summaryEdge.initialFacts) { - if (!methodInitialFact.matchNDInitial(summaryInitialFact)) { + for (summaryInitialFact in summaryEdge.initial) { + if (!currentEdgeFactAp.matchNDInitial(summaryInitialFact)) { requiredFacts.add(summaryInitialFact) } } - if (requiredFacts.size == summaryEdge.initialFacts.size) continue + if (requiredFacts.size == summaryEdge.initial.size) continue val requiredInitials = mutableListOf>>() for (requiredFact in requiredFacts) { @@ -1314,13 +1301,7 @@ class NormalMethodAnalyzer( factAtStatement.rebase(requiredFact.base).matchNDInitial(requiredFact) } - val mappedRequiredFacts = analysisContext.methodCallFactMapper.mapMethodExitToReturnFlowFact( - currentEdge.statement, requiredFact - ) - - val factInitials = mappedRequiredFacts.flatMapTo(hashSetOf()) { - searcher.findMatchingEdgesInitialFacts(currentEdge.statement, it) - } + val factInitials = searcher.findMatchingEdgesInitialFacts(currentEdge.statement, requiredFact) if (factInitials.isEmpty()) { continue@nextSummary @@ -1342,7 +1323,7 @@ class NormalMethodAnalyzer( summaryHandler.handleZeroToFact( currentEdgeFactAp, EdgeRefinement.UniverseRefinement, - summaryEdge.summaryEdge() + summaryEdge ) } @@ -1352,7 +1333,7 @@ class NormalMethodAnalyzer( initialFact, currentEdgeFactAp, EdgeRefinement.UniverseRefinement, - summaryEdge.summaryEdge() + summaryEdge ) } @@ -1361,7 +1342,7 @@ class NormalMethodAnalyzer( ndSummaryInitial, currentEdgeFactAp, EdgeRefinement.UniverseRefinement, - summaryEdge.summaryEdge() + summaryEdge ) } } @@ -1375,7 +1356,7 @@ class NormalMethodAnalyzer( currentEdge.initialFactAp, currentEdgeFactAp, EdgeRefinement.IdRefinement, - summaryEdge.summaryEdge() + summaryEdge ) } @@ -1384,7 +1365,7 @@ class NormalMethodAnalyzer( ndSummaryInitial, currentEdgeFactAp, EdgeRefinement.UniverseRefinement, - summaryEdge.summaryEdge() + summaryEdge ) } } @@ -1395,7 +1376,7 @@ class NormalMethodAnalyzer( ndSummaryInitial + currentEdge.initialFacts, currentEdgeFactAp, EdgeRefinement.UniverseRefinement, - summaryEdge.summaryEdge() + summaryEdge ) } } @@ -1431,9 +1412,9 @@ class NormalMethodAnalyzer( } override fun resolveCalleeFact(statement: CommonInst, factAp: FinalFactAp): Set = - analysisContext.methodCallFactMapper.mapMethodExitToReturnFlowFact( - statement, factAp, FactTypeChecker.Dummy - ).toSet() + analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) + .prepareSummaryFinalFact(factAp, FactTypeChecker.Dummy) + .toSet() private fun updateTaintRulesStats( finalEdgeFact: FinalFactAp?, @@ -1451,7 +1432,6 @@ class NormalMethodAnalyzer( } private fun FactToFact.summaryEdge() = SummaryEdge.F2F(this.methodEntryPoint, initialFactAp, factAp) - private fun NDFactToFact.summaryEdge() = SummaryEdge.NdF2F(this.methodEntryPoint, initialFacts, factAp) override fun cleanup() { methodEntryPointsCache = hashMapOf() diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt index f1f276fd0..c11decfd2 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt @@ -10,7 +10,6 @@ import org.opentaint.dataflow.ap.ifds.TaintAnalysisUnitRunner import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition -import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodStartPrecondition import org.opentaint.dataflow.graph.MethodInstGraph @@ -91,12 +90,6 @@ interface AnalysisManager: LanguageManager { statement: CommonInst, ): MethodCallSummaryHandler - fun getMethodCallSummaryPreconditionHandler( - apManager: ApManager, - analysisContext: MethodAnalysisContext, - statement: CommonInst, - ): MethodCallSummaryPreconditionHandler - fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodAnalysisContext.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodAnalysisContext.kt index 29b22f302..731f4e88a 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodAnalysisContext.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodAnalysisContext.kt @@ -4,7 +4,4 @@ import org.opentaint.dataflow.ap.ifds.MethodEntryPoint interface MethodAnalysisContext { val methodEntryPoint: MethodEntryPoint - - // todo: remove, required for trace generation - val methodCallFactMapper: MethodCallFactMapper } diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt index 04a1b606e..7cec7b63c 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt @@ -12,6 +12,7 @@ import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.MethodSequentFlowFunction.Sequent import org.opentaint.dataflow.ap.ifds.analysis.MethodSequentFlowFunction.TraceInfo +import org.opentaint.dataflow.util.cartesianProductMapTo interface MethodCallSummaryHandler { val factTypeChecker: FactTypeChecker @@ -33,18 +34,20 @@ interface MethodCallSummaryHandler { ) : SummaryEdge } - fun mapMethodExitToReturnFlowFact(fact: FinalFactAp): List + fun prepareSummaryInitialFact(fact: InitialFactAp): List + + fun prepareSummaryFinalFact(fact: FinalFactAp, checker: FactTypeChecker = factTypeChecker): List fun handleZeroToZero(summaryFact: FinalFactAp?): Set { if (summaryFact == null) return setOf(Sequent.ZeroToZero) - val summaryExitFacts = mapMethodExitToReturnFlowFact(summaryFact) - return summaryExitFacts.mapTo(hashSetOf()) { - Sequent.ZeroToFact(it, TraceInfo.ApplySummary) - } + return setOf(Sequent.ZeroToFact(summaryFact, TraceInfo.ApplySummary)) } - fun prepareZeroToFactSummary(summaryEdge: Edge.ZeroToFact): List = listOf(summaryEdge) + fun prepareZeroToFactSummary(summaryEdge: Edge.ZeroToFact): List = + prepareSummaryFinalFact(summaryEdge.factAp).map { + Edge.ZeroToFact(summaryEdge.methodEntryPoint, summaryEdge.statement, it) + } fun handleZeroToFact( currentFactAp: FinalFactAp, @@ -82,7 +85,14 @@ interface MethodCallSummaryHandler { Sequent.FactToFact(initialFactAp.refine(initialFactRefinement), summaryFactAp, TraceInfo.ApplySummary) } - fun prepareFactToFactSummary(summaryEdge: Edge.FactToFact): List = listOf(summaryEdge) + fun prepareFactToFactSummary(summaryEdge: Edge.FactToFact): List { + val finalFacts = prepareSummaryFinalFact(summaryEdge.factAp) + return prepareSummaryInitialFact(summaryEdge.initialFactAp).flatMap { initialFactAp -> + finalFacts.map { factAp -> + Edge.FactToFact(summaryEdge.methodEntryPoint, initialFactAp, summaryEdge.statement, factAp) + } + } + } fun handleNDFactToFact( initialFacts: Set, @@ -109,7 +119,17 @@ interface MethodCallSummaryHandler { ) } - fun prepareNDFactToFactSummary(summaryEdge: Edge.NDFactToFact): List = listOf(summaryEdge) + fun prepareNDFactToFactSummary(summaryEdge: Edge.NDFactToFact): List { + val finalFacts = prepareSummaryFinalFact(summaryEdge.factAp) + return summaryEdge.initialFacts + .map { prepareSummaryInitialFact(it) } + .cartesianProductMapTo { it.toHashSet() } + .flatMap { initialFacts -> + finalFacts.map { factAp -> + SummaryEdge.NdF2F(summaryEdge.methodEntryPoint, initialFacts, factAp) + } + } + } fun InitialFactAp.refine(exclusionSet: ExclusionSet?) = if (exclusionSet == null) this else replaceExclusions(exclusionSet) @@ -121,35 +141,40 @@ interface MethodCallSummaryHandler { createSideEffectRequirement: (refinement: ExclusionSet) -> Sequent?, handleSummaryEdge: (initialFactRefinement: ExclusionSet?, summaryFactAp: FinalFactAp) -> Sequent ): Set { - val mappedSummaryFacts = mapMethodExitToReturnFlowFact(summaryEdge.final) + val summaryFinalFact = summaryEdge.final return when (summaryEffect) { - is SummaryEdgeApplication -> mappedSummaryFacts.mapNotNullTo(hashSetOf()) { mappedSummaryFact -> - val summaryFactAp = mappedSummaryFact - .concat(factTypeChecker, summaryEffect.delta) - ?: return@mapNotNullTo null + is SummaryEdgeApplication -> { + val summaryFactAp = summaryFinalFact.concat(factTypeChecker, summaryEffect.delta) + ?: return emptySet() when (summaryEffect) { is SummaryApRefinement -> { // todo: filter exclusions val fact = summaryFactAp.replaceExclusions(currentFactAp.exclusions) - handleSummaryEdge(null, fact) + setOf(handleSummaryEdge(null, fact)) } is SummaryExclusionRefinement -> { val fact = summaryFactAp.replaceExclusions(summaryEffect.exclusion) - handleSummaryEdge(summaryEffect.exclusion, fact) + setOf(handleSummaryEdge(summaryEffect.exclusion, fact)) } } } - is EdgeRefinement.UniverseRefinement -> mappedSummaryFacts.mapTo(hashSetOf()) { - handleSummaryEdge(ExclusionSet.Universe, it.replaceExclusions(ExclusionSet.Universe)) - } - - is EdgeRefinement.IdRefinement -> mappedSummaryFacts.mapTo(hashSetOf()) { - handleSummaryEdge(currentFactAp.exclusions, it.replaceExclusions(currentFactAp.exclusions)) - } + is EdgeRefinement.UniverseRefinement -> setOf( + handleSummaryEdge( + ExclusionSet.Universe, + summaryFinalFact.replaceExclusions(ExclusionSet.Universe) + ) + ) + + is EdgeRefinement.IdRefinement -> setOf( + handleSummaryEdge( + currentFactAp.exclusions, + summaryFinalFact.replaceExclusions(currentFactAp.exclusions) + ) + ) } } } diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt index e444138d4..a831d97e2 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt @@ -11,6 +11,10 @@ import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.MethodSequentFlowFunction.Sequent interface MethodSideEffectSummaryHandler { + fun prepareSideEffectSummary( + sideEffectSummary: SideEffectSummary.FactSideEffectSummary, + ): List + fun handleZeroToZero( sideEffects: List, ): Set = emptySet() diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt deleted file mode 100644 index 41c23ba05..000000000 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPreconditionHandler.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.opentaint.dataflow.ap.ifds.trace - -import org.opentaint.dataflow.ap.ifds.Edge - -interface MethodCallSummaryPreconditionHandler { - fun prepareFactToFactSummary(summaryEdge: Edge.FactToFact): List = listOf(summaryEdge) -} diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt index 7f3c0b31d..02cb41298 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodForwardTraceResolver.kt @@ -264,16 +264,17 @@ class MethodForwardTraceResolver( val calleeInitialFactAp = callerEdge.factAp.rebase(startFactBase) val summaries = manager.findFactSummaryEdges(ep, calleeInitialFactAp) - val applicableSummaries = summaries.filter { isApplicableExitToReturnEdge(it) } - val handler = analysisManager.getMethodCallSummaryHandler( apManager, analysisContext, callerEdge.statement ) + val applicableSummaries = summaries + .filter { isApplicableExitToReturnEdge(it) } + .flatMap { handler.prepareFactToFactSummary(it) } + val summaryApplied = applyMethodSummaries( currentEdge = callerEdge, callerFact = callerFact, - methodInitialFactBase = startFactBase, methodSummaries = applicableSummaries, handleSummaryEdge = handler::handleZeroToFact ) @@ -292,17 +293,15 @@ class MethodForwardTraceResolver( private fun TraceBuilder.applyMethodSummaries( currentEdge: ZeroToFact, callerFact: FinalFactAp, - methodInitialFactBase: AccessPathBase, methodSummaries: List, handleSummaryEdge: (currentFactAp: FinalFactAp, summaryEffect: SummaryEdgeApplication, summaryEdge: SummaryEdge) -> Set, ): Boolean { var summaryApplied = false - val methodInitialFact = callerFact.rebase(methodInitialFactBase) val summaries = methodSummaries.groupByTo(hashMapOf()) { it.initialFactAp } for ((summaryInitialFact, summaryEdges) in summaries) { val summaryEdgeEffects = MethodSummaryEdgeApplicationUtils.tryApplySummaryEdge( - methodInitialFact, summaryInitialFact + callerFact, summaryInitialFact ) for (summaryEdgeEffect in summaryEdgeEffects) { diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt index 645498513..d71187782 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt @@ -20,7 +20,6 @@ import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.AnalysisManager import org.opentaint.dataflow.ap.ifds.analysis.MethodAnalysisContext -import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFactMapper import org.opentaint.dataflow.ap.ifds.analysis.MethodCallResolver.MethodCallResolutionResult import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallResolutionPreconditionFact @@ -77,9 +76,11 @@ class MethodTraceResolver( private val methodEntryPoint: MethodEntryPoint = analysisContext.methodEntryPoint private val analysisManager: AnalysisManager get() = runner.analysisManager private val manager: AnalysisUnitRunnerManager get() = runner.manager - private val methodCallFactMapper: MethodCallFactMapper get() = analysisContext.methodCallFactMapper private val apManager: ApManager get() = runner.apManager + private fun summaryHandler(statement: CommonInst) = + analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) + // Enum can give non-determinacy as its entries have new hash code on every JVM run. // Override hashcode() and equals() when using enum as a field in classes whose objects // can be stored in sets etc. @@ -452,8 +453,9 @@ class MethodTraceResolver( statement: CommonInst, calleeEntry: TraceEntry.MethodEntry ): List { + val handler = summaryHandler(statement) val traceEdges = calleeEntry.facts.flatMap { fact -> - val mappedFacts = methodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) + val mappedFacts = handler.prepareSummaryInitialFact(fact) mappedFacts.map { resolveIntraProceduralTraceEdge(statement, it, includeStatement = false) } } @@ -1645,7 +1647,7 @@ class MethodTraceResolver( startFact: MethodCallPrecondition.CallToStartResolved, statement: CommonInst ) { - val summaryHandler = analysisManager.getMethodCallSummaryPreconditionHandler(apManager, analysisContext, statement) + val summaryHandler = summaryHandler(statement) val resolvedCallSummaries = mutableListOf() val methodSummaries = manager.findFactToFactSummaryEdges(callee, startFact.startFactBase) @@ -1658,31 +1660,25 @@ class MethodTraceResolver( if (deltas.isEmpty()) continue - val applicableSummaries = summaryHandler.prepareFactToFactSummary(summaryEdge) - applicableSummaries.forEach { applicableSummary -> - // it is ok to map call arguments via exit2return - val mappedSummaryInitial = methodCallFactMapper.mapMethodExitToReturnFlowFact( - statement, applicableSummary.initialFactAp - ) + val mappedSummaryInitial = summaryHandler.prepareSummaryInitialFact(summaryEdge.initialFactAp) - for ((matchedEntryFact, delta) in deltas) { - // todo: remove this check? - if (!mappedSummaryFact.contains(matchedEntryFact)) continue - - for (mappedSummaryInitialFact in mappedSummaryInitial) { - val precondition = mappedSummaryInitialFact - .concat(delta) - .replaceExclusions(callerFact.exclusions) - - resolvedCallSummaries.addCallSummaryEntry( - currentTraceEdge = currentEdge, - precondition = precondition, - preconditionDelta = delta, - callee = callee, - summaryFinalFact = matchedEntryFact, - summaryEdge = summaryEdge, - ) - } + for ((matchedEntryFact, delta) in deltas) { + // todo: remove this check? + if (!mappedSummaryFact.contains(matchedEntryFact)) continue + + for (mappedSummaryInitialFact in mappedSummaryInitial) { + val precondition = mappedSummaryInitialFact + .concat(delta) + .replaceExclusions(callerFact.exclusions) + + resolvedCallSummaries.addCallSummaryEntry( + currentTraceEdge = currentEdge, + precondition = precondition, + preconditionDelta = delta, + callee = callee, + summaryFinalFact = matchedEntryFact, + summaryEdge = summaryEdge, + ) } } } @@ -1699,7 +1695,7 @@ class MethodTraceResolver( if (!mappedSummaryFact.contains(callerFact)) continue val mappedSummaryInitialFacts = summaryEdge.initialFacts.map { - methodCallFactMapper.mapMethodExitToReturnFlowFact(statement, it) + summaryHandler.prepareSummaryInitialFact(it) } mappedSummaryInitialFacts.cartesianProductMapTo { mappedFactGroup -> diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt index b653d836d..ca17f100e 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt @@ -20,7 +20,6 @@ import org.opentaint.dataflow.ap.ifds.analysis.MethodStartFlowFunction import org.opentaint.dataflow.ap.ifds.taint.ExternalMethodTracker import org.opentaint.dataflow.ap.ifds.taint.TaintAnalysisContext import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition -import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodStartPrecondition import org.opentaint.dataflow.go.GoCallExpr @@ -31,7 +30,6 @@ import org.opentaint.dataflow.go.graph.GoApplicationGraph import org.opentaint.dataflow.go.rules.GoTaintAnalysisContext import org.opentaint.dataflow.go.rules.GoTaintRulesProvider import org.opentaint.dataflow.go.trace.GoMethodCallPrecondition -import org.opentaint.dataflow.go.trace.GoMethodCallSummaryPreconditionHandler import org.opentaint.dataflow.go.trace.GoMethodSequentPrecondition import org.opentaint.dataflow.go.trace.GoMethodStartPrecondition import org.opentaint.dataflow.graph.MethodInstGraph @@ -160,19 +158,13 @@ class GoAnalysisManager( ) } - override fun getMethodCallSummaryPreconditionHandler( - apManager: ApManager, - analysisContext: MethodAnalysisContext, - statement: CommonInst - ): MethodCallSummaryPreconditionHandler = GoMethodCallSummaryPreconditionHandler - override fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, statement: CommonInst, runner: AnalysisRunner, ): MethodSideEffectSummaryHandler { - return GoMethodSideEffectHandler(runner) + return GoMethodSideEffectHandler(statement as GoIRInst, runner) } override fun getMethodStartPrecondition( diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodAnalysisContext.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodAnalysisContext.kt index f6ce7b2e3..2285ba368 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodAnalysisContext.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodAnalysisContext.kt @@ -3,9 +3,7 @@ package org.opentaint.dataflow.go.analysis import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.TaintAnalysisManager import org.opentaint.dataflow.ap.ifds.analysis.MethodAnalysisContext -import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFactMapper import org.opentaint.dataflow.go.GoClosureTracker.ClosureTracker -import org.opentaint.dataflow.go.GoMethodCallFactMapper import org.opentaint.dataflow.go.analysis.alias.GoLocalAliasAnalysis import org.opentaint.dataflow.go.rules.GoTaintAnalysisContext import org.opentaint.dataflow.util.int2ObjectMap @@ -26,9 +24,6 @@ class GoMethodAnalysisContext( val phase: TaintAnalysisManager.Phase get() = analysisManager.phase - override val methodCallFactMapper: MethodCallFactMapper - get() = GoMethodCallFactMapper - val method: GoIRFunction get() = methodEntryPoint.method as GoIRFunction diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt index be035855a..e11bc9489 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt @@ -6,6 +6,7 @@ import org.opentaint.dataflow.ap.ifds.FactTypeChecker import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp +import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.MethodCallSummaryHandler import org.opentaint.dataflow.ap.ifds.analysis.MethodCallSummaryHandler.SummaryEdge import org.opentaint.dataflow.ap.ifds.analysis.MethodSequentFlowFunction.Sequent @@ -24,8 +25,12 @@ class GoMethodCallSummaryHandler( ) : MethodCallSummaryHandler { override val factTypeChecker: FactTypeChecker = FactTypeChecker.Dummy - override fun mapMethodExitToReturnFlowFact(fact: FinalFactAp): List { - return GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, factTypeChecker) + override fun prepareSummaryInitialFact(fact: InitialFactAp): List { + return GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) + } + + override fun prepareSummaryFinalFact(fact: FinalFactAp, checker: FactTypeChecker): List { + return GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, checker) } private val callExpr: GoCallExpr by lazy { @@ -41,24 +46,26 @@ class GoMethodCallSummaryHandler( } override fun prepareFactToFactSummary(summaryEdge: Edge.FactToFact): List = - summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).map { (resultFact, refinement) -> - Edge.FactToFact( + summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).flatMap { (resultFact, refinement) -> + val rewrittenEdge = Edge.FactToFact( summaryEdge.methodEntryPoint, refinement.refineFact(summaryEdge.initialFactAp), summaryEdge.statement, refinement.refineFact(resultFact) ) + super.prepareFactToFactSummary(rewrittenEdge) } - override fun prepareNDFactToFactSummary(summaryEdge: Edge.NDFactToFact): List = - summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).map { (resultFact, refinement) -> + override fun prepareNDFactToFactSummary(summaryEdge: Edge.NDFactToFact): List = + summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).flatMap { (resultFact, refinement) -> check(!refinement.hasRefinement) { "Can't refine NDF2F edge" } - Edge.NDFactToFact( + val rewrittenEdge = Edge.NDFactToFact( summaryEdge.methodEntryPoint, summaryEdge.initialFacts, summaryEdge.statement, resultFact, ) + super.prepareNDFactToFactSummary(rewrittenEdge) } override fun handleZeroToZero(summaryFact: FinalFactAp?): Set = diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt index bf0fdd230..c913073c5 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt @@ -1,8 +1,18 @@ package org.opentaint.dataflow.go.analysis import org.opentaint.dataflow.ap.ifds.AnalysisRunner +import org.opentaint.dataflow.ap.ifds.SideEffectSummary +import org.opentaint.dataflow.go.GoMethodCallFactMapper import org.opentaint.dataflow.taint.MethodSideEffectHandlerWithAnyAccessorRequestHandling +import org.opentaint.ir.go.inst.GoIRInst class GoMethodSideEffectHandler( + private val statement: GoIRInst, override val runner: AnalysisRunner -) : MethodSideEffectHandlerWithAnyAccessorRequestHandling +) : MethodSideEffectHandlerWithAnyAccessorRequestHandling { + override fun prepareSideEffectSummary( + sideEffectSummary: SideEffectSummary.FactSideEffectSummary, + ): List = + GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, sideEffectSummary.initialFactAp) + .map { sideEffectSummary.copy(initialFactAp = it) } +} diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt deleted file mode 100644 index da3ce3247..000000000 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPreconditionHandler.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.opentaint.dataflow.go.trace - -import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler - -object GoMethodCallSummaryPreconditionHandler : MethodCallSummaryPreconditionHandler diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt index a811eb4c6..98f615535 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt @@ -21,7 +21,6 @@ import org.opentaint.dataflow.ap.ifds.analysis.MethodStartFlowFunction import org.opentaint.dataflow.ap.ifds.taint.ExternalMethodTracker import org.opentaint.dataflow.ap.ifds.taint.TaintAnalysisContext import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition -import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodStartPrecondition import org.opentaint.dataflow.graph.MethodInstGraph @@ -37,7 +36,6 @@ import org.opentaint.dataflow.jvm.ap.ifds.jIRDowncast import org.opentaint.dataflow.jvm.ap.ifds.taint.JIRTaintAnalysisContext import org.opentaint.dataflow.jvm.ap.ifds.taint.TaintRulesProvider import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodCallPrecondition -import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodCallSummaryPreconditionHandler import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodSequentPrecondition import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodStartPrecondition import org.opentaint.dataflow.jvm.ifds.JIRUnitResolver @@ -238,12 +236,6 @@ class JIRAnalysisManager( } } - override fun getMethodCallSummaryPreconditionHandler( - apManager: ApManager, - analysisContext: MethodAnalysisContext, - statement: CommonInst - ): MethodCallSummaryPreconditionHandler = JIRMethodCallSummaryPreconditionHandler - override fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, @@ -253,7 +245,7 @@ class JIRAnalysisManager( jIRDowncast(statement) jIRDowncast(analysisContext) - return JIRMethodSideEffectHandler(runner) + return JIRMethodSideEffectHandler(statement, runner) } override fun getMethodCallPrecondition( diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodAnalysisContext.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodAnalysisContext.kt index d9837eac0..e5b9d9d74 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodAnalysisContext.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodAnalysisContext.kt @@ -5,12 +5,10 @@ import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.TaintAnalysisManager.Phase import org.opentaint.dataflow.ap.ifds.TaintMarkAccessor import org.opentaint.dataflow.ap.ifds.analysis.MethodAnalysisContext -import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFactMapper import org.opentaint.dataflow.jvm.ap.ifds.JIRFactTypeChecker import org.opentaint.dataflow.jvm.ap.ifds.JIRLambdaTracker import org.opentaint.dataflow.jvm.ap.ifds.JIRLocalAliasAnalysis import org.opentaint.dataflow.jvm.ap.ifds.JIRLocalVariableReachability -import org.opentaint.dataflow.jvm.ap.ifds.JIRMethodCallFactMapper import org.opentaint.dataflow.jvm.ap.ifds.taint.JIRTaintAnalysisContext import org.opentaint.dataflow.util.SoftReferenceManager import org.opentaint.dataflow.util.int2ObjectMap @@ -31,9 +29,6 @@ class JIRMethodAnalysisContext( val phase: Phase get() = analysisManager.phase - override val methodCallFactMapper: MethodCallFactMapper - get() = JIRMethodCallFactMapper - val taintMarksAssignedOnMethodEnter = hashSetOf() val lambdaCallResolution = Int2ObjectOpenHashMap() diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt index b31fa004a..ee692a875 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt @@ -6,6 +6,7 @@ import org.opentaint.dataflow.ap.ifds.FactTypeChecker import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp +import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.MethodCallSummaryHandler import org.opentaint.dataflow.ap.ifds.analysis.MethodCallSummaryHandler.SummaryEdge import org.opentaint.dataflow.ap.ifds.analysis.MethodSequentFlowFunction.Sequent @@ -23,8 +24,11 @@ class JIRMethodCallSummaryHandler( JIRMethodCallRuleBasedSummaryRewriter(statement, analysisContext, apManager) } - override fun mapMethodExitToReturnFlowFact(fact: FinalFactAp): List = - JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, factTypeChecker) + override fun prepareSummaryInitialFact(fact: InitialFactAp): List = + JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) + + override fun prepareSummaryFinalFact(fact: FinalFactAp, checker: FactTypeChecker): List = + JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, checker) override fun handleZeroToZero(summaryFact: FinalFactAp?): Set = super.handleZeroToZero(summaryFact).flatMapTo(hashSetOf()) { seq -> @@ -69,24 +73,26 @@ class JIRMethodCallSummaryHandler( } override fun prepareFactToFactSummary(summaryEdge: Edge.FactToFact): List = - summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).map { (resultFact, refinement) -> - Edge.FactToFact( + summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).flatMap { (resultFact, refinement) -> + val rewrittenEdge = Edge.FactToFact( summaryEdge.methodEntryPoint, refinement.refineFact(summaryEdge.initialFactAp), summaryEdge.statement, refinement.refineFact(resultFact) ) + super.prepareFactToFactSummary(rewrittenEdge) } - override fun prepareNDFactToFactSummary(summaryEdge: Edge.NDFactToFact): List = - summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).map { (resultFact, refinement) -> + override fun prepareNDFactToFactSummary(summaryEdge: Edge.NDFactToFact): List = + summaryRewriter.rewriteSummaryFact(summaryEdge.factAp).flatMap { (resultFact, refinement) -> check(!refinement.hasRefinement) { "Can't refine NDF2F edge" } - Edge.NDFactToFact( + val rewrittenEdge = Edge.NDFactToFact( summaryEdge.methodEntryPoint, summaryEdge.initialFacts, summaryEdge.statement, resultFact, ) + super.prepareNDFactToFactSummary(rewrittenEdge) } private fun applyCallAliases(fact: FinalFactAp, body: (FinalFactAp) -> Unit) { diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt index 0ad1697d5..66ac0a281 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt @@ -1,8 +1,18 @@ package org.opentaint.dataflow.jvm.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.AnalysisRunner +import org.opentaint.dataflow.ap.ifds.SideEffectSummary +import org.opentaint.dataflow.jvm.ap.ifds.JIRMethodCallFactMapper import org.opentaint.dataflow.taint.MethodSideEffectHandlerWithAnyAccessorRequestHandling +import org.opentaint.ir.api.jvm.cfg.JIRInst class JIRMethodSideEffectHandler( + private val statement: JIRInst, override val runner: AnalysisRunner -) : MethodSideEffectHandlerWithAnyAccessorRequestHandling +) : MethodSideEffectHandlerWithAnyAccessorRequestHandling { + override fun prepareSideEffectSummary( + sideEffectSummary: SideEffectSummary.FactSideEffectSummary, + ): List = + JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, sideEffectSummary.initialFactAp) + .map { sideEffectSummary.copy(initialFactAp = it) } +} diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt index 6b365878f..c336a9747 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt @@ -5,7 +5,6 @@ import org.opentaint.dataflow.ap.ifds.MethodWithContext import org.opentaint.dataflow.ap.ifds.TaintMarkAccessor import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.InitialFactAp -import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFactMapper import org.opentaint.dataflow.ap.ifds.taint.TaintAnalysisContext.RuleWithCondition import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallFailurePreconditionFact @@ -43,8 +42,6 @@ class JIRMethodCallPrecondition( private val callExpr: JIRCallExpr, private val statement: JIRInst, ) : MethodCallPrecondition.Default { - private val methodCallFactMapper: MethodCallFactMapper get() = analysisContext.methodCallFactMapper - private val taintCtx get() = analysisContext.taint override fun factPrecondition(fact: InitialFactAp): List> { @@ -190,5 +187,5 @@ class JIRMethodCallPrecondition( statement.location.method.instList.toList() override fun mapExit2Return(fact: InitialFactAp): List = - methodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) + JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) } diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt deleted file mode 100644 index 9ecef9830..000000000 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPreconditionHandler.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.opentaint.dataflow.jvm.ap.ifds.trace - -import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPreconditionHandler - -object JIRMethodCallSummaryPreconditionHandler : MethodCallSummaryPreconditionHandler From db8f27047d0d1f9e92492a0f2de3029dfc34695e Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Tue, 11 Aug 2026 15:36:07 +0300 Subject: [PATCH 06/12] Rewrite call2return fact propagation --- .../dataflow/ap/ifds/MethodAnalyzer.kt | 127 +++++++----------- 1 file changed, 49 insertions(+), 78 deletions(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index 63675fd6a..6398cb372 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -405,18 +405,6 @@ class NormalMethodAnalyzer( handleUnchangedStatementEdge(edge) } - is MethodCallFlowFunction.Drop -> { - // do nothing - } - - is MethodCallFlowFunction.CallToReturnZeroFact -> { - handleStatementEdge(edge, ZeroToZero(methodEntryPoint, edge.statement)) - } - - is MethodCallFlowFunction.CallToReturnZFact -> { - handleStatementEdge(edge, ZeroToFact(methodEntryPoint, edge.statement, fact.factAp)) - } - is MethodCallFlowFunction.CallToStartZeroFact -> { val callerEdge = ZeroToZero(methodEntryPoint, edge.statement) @@ -432,21 +420,11 @@ class NormalMethodAnalyzer( resolveMethodCall(callExpr, edge.statement, handler, failureHandler) } - is MethodCallFlowFunction.CallToReturnFFact -> { - val edgeAfterStatement = FactToFact(methodEntryPoint, fact.initialFactAp, edge.statement, fact.factAp) - handleStatementEdge(edge, edgeAfterStatement) - } - - is MethodCallFlowFunction.CallToReturnNonDistributiveFact -> { - val edgeAfterStatement = NDFactToFact( - methodEntryPoint, fact.initialFacts, edge.statement, fact.factAp - ) - handleStatementEdge(edge, edgeAfterStatement) - } - is MethodCallFlowFunction.ZeroSideEffect -> { addZeroSideEffect(fact.kind) } + + is MethodCallFlowFunction.Call2ReturnFact -> propagateCall2ReturnFact(edge, fact) } } @@ -460,20 +438,6 @@ class NormalMethodAnalyzer( handleUnchangedStatementEdge(edge) } - is MethodCallFlowFunction.Drop -> { - // do nothing - } - - is MethodCallFlowFunction.CallToReturnFFact -> { - val edgeAfterStatement = FactToFact(methodEntryPoint, fact.initialFactAp, edge.statement, fact.factAp) - handleStatementEdge(edge, edgeAfterStatement) - } - - is MethodCallFlowFunction.CallToReturnZFact -> { - val edgeAfterStatement = ZeroToFact(methodEntryPoint, edge.statement, fact.factAp) - handleStatementEdge(edge, edgeAfterStatement) - } - is MethodCallFlowFunction.CallToStartFFact -> { val callerEdge = FactToFact(methodEntryPoint, fact.initialFactAp, edge.statement, fact.callerFactAp) @@ -492,12 +456,7 @@ class NormalMethodAnalyzer( addFactSideEffect(edge, fact.initialFactAp, fact.kind) } - is MethodCallFlowFunction.CallToReturnNonDistributiveFact -> { - val edgeAfterStatement = NDFactToFact( - methodEntryPoint, fact.initialFacts, edge.statement, fact.factAp - ) - handleStatementEdge(edge, edgeAfterStatement) - } + is MethodCallFlowFunction.Call2ReturnFact -> propagateCall2ReturnFact(edge, fact) } } @@ -511,22 +470,6 @@ class NormalMethodAnalyzer( handleUnchangedStatementEdge(edge) } - is MethodCallFlowFunction.Drop -> { - // do nothing - } - - is MethodCallFlowFunction.CallToReturnNonDistributiveFact -> { - val edgeAfterStatement = NDFactToFact( - methodEntryPoint, fact.initialFacts, edge.statement, fact.factAp - ) - handleStatementEdge(edge, edgeAfterStatement) - } - - is MethodCallFlowFunction.CallToReturnZFact -> { - val edgeAfterStatement = ZeroToFact(methodEntryPoint, edge.statement, fact.factAp) - handleStatementEdge(edge, edgeAfterStatement) - } - is MethodCallFlowFunction.CallToStartNDFFact -> { val callerEdge = NDFactToFact(methodEntryPoint, fact.initialFacts, edge.statement, fact.callerFactAp) @@ -534,11 +477,12 @@ class NormalMethodAnalyzer( val failureHandler = MethodCallResolutionFailureHandler.NDFactToFactHandler(callerEdge, fact.startFactBase) resolveMethodCall(callExpr, edge.statement, handler, failureHandler) } + + is MethodCallFlowFunction.Call2ReturnFact -> propagateCall2ReturnFact(edge, fact) } } private fun propagateZeroCallSuccessFact( - callExpr: CommonCallExpr, edge: ZeroInitialEdge, fact: MethodCallFlowFunction.ZeroCallSuccessFact, method: MethodWithContext, @@ -554,15 +498,11 @@ class NormalMethodAnalyzer( handleMethodCall(method) { runner.subscribeOnMethodSummaries(callerEdge, it, fact.startFactBase) } } - is MethodCallFlowFunction.CallToReturnFFact, - is MethodCallFlowFunction.CallToReturnNonDistributiveFact, - is MethodCallFlowFunction.CallToReturnZFact, - is MethodCallFlowFunction.CallToReturnZeroFact -> propagateZeroCallFact(callExpr, edge, fact) + is MethodCallFlowFunction.Call2ReturnFact -> propagateCall2ReturnFact(edge, fact) } } private fun propagateFactCallSuccessFact( - callExpr: CommonCallExpr, edge: FactToFact, fact: MethodCallFlowFunction.FactCallSuccessFact, method: MethodWithContext, @@ -574,16 +514,19 @@ class NormalMethodAnalyzer( handleMethodCall(method) { runner.subscribeOnMethodSummaries(callerEdge, it, fact.startFactBase) } } - is MethodCallFlowFunction.CallToReturnFFact, - is MethodCallFlowFunction.CallToReturnZFact, - is MethodCallFlowFunction.CallToReturnNonDistributiveFact, - is MethodCallFlowFunction.SideEffectRequirement, - is MethodCallFlowFunction.FactSideEffect -> propagateFactCallFact(callExpr, edge, fact) + is MethodCallFlowFunction.SideEffectRequirement -> { + addSideEffectRequirement(edge, fact.initialFactAp) + } + + is MethodCallFlowFunction.FactSideEffect -> { + addFactSideEffect(edge, fact.initialFactAp, fact.kind) + } + + is MethodCallFlowFunction.Call2ReturnFact -> propagateCall2ReturnFact(edge, fact) } } private fun propagateNDFactCallSuccessFact( - callExpr: CommonCallExpr, edge: NDFactToFact, fact: MethodCallFlowFunction.NDFactCallSuccessFact, method: MethodWithContext, @@ -594,8 +537,36 @@ class NormalMethodAnalyzer( handleMethodCall(method) { runner.subscribeOnMethodSummaries(callerEdge, it, fact.startFactBase) } } - is MethodCallFlowFunction.CallToReturnZFact, - is MethodCallFlowFunction.CallToReturnNonDistributiveFact -> propagateNDFactCallFact(callExpr, edge, fact) + is MethodCallFlowFunction.Call2ReturnFact -> propagateCall2ReturnFact(edge, fact) + } + } + + private fun propagateCall2ReturnFact(edge: Edge, fact: MethodCallFlowFunction.Call2ReturnFact) { + when (fact) { + is MethodCallFlowFunction.CallToReturnZeroFact -> { + handleStatementEdge(edge, ZeroToZero(methodEntryPoint, edge.statement)) + } + + is MethodCallFlowFunction.CallToReturnZFact -> { + val edgeAfterStatement = ZeroToFact(methodEntryPoint, edge.statement, fact.factAp) + handleStatementEdge(edge, edgeAfterStatement) + } + + is MethodCallFlowFunction.CallToReturnFFact -> { + val edgeAfterStatement = FactToFact(methodEntryPoint, fact.initialFactAp, edge.statement, fact.factAp) + handleStatementEdge(edge, edgeAfterStatement) + } + + is MethodCallFlowFunction.CallToReturnNonDistributiveFact -> { + val edgeAfterStatement = NDFactToFact( + methodEntryPoint, fact.initialFacts, edge.statement, fact.factAp + ) + handleStatementEdge(edge, edgeAfterStatement) + } + + is MethodCallFlowFunction.Drop -> { + // do nothing + } } } @@ -820,27 +791,27 @@ class NormalMethodAnalyzer( when (handler) { is MethodCallHandler.ZeroToZeroHandler -> { flowFunction.propagateZeroToZeroResolutionSuccess(method).forEach { - propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, method) + propagateZeroCallSuccessFact(handler.currentEdge, it, method) } } is MethodCallHandler.ZeroToFactHandler -> { flowFunction.propagateZeroToFactResolutionSuccess(handler.currentEdge.factAp, handler.startFactBase, method).forEach { - propagateZeroCallSuccessFact(callExpr, handler.currentEdge, it, method) + propagateZeroCallSuccessFact(handler.currentEdge, it, method) } } is MethodCallHandler.FactToFactHandler -> { val edge = handler.currentEdge flowFunction.propagateFactToFactResolutionSuccess(edge.initialFactAp, edge.factAp, handler.startFactBase, method).forEach { - propagateFactCallSuccessFact(callExpr, edge, it, method) + propagateFactCallSuccessFact(edge, it, method) } } is MethodCallHandler.NDFactToFactHandler -> { val edge = handler.currentEdge flowFunction.propagateNDFactToFactResolutionSuccess(edge.initialFacts, edge.factAp, handler.startFactBase, method).forEach { - propagateNDFactCallSuccessFact(callExpr, edge, it, method) + propagateNDFactCallSuccessFact(edge, it, method) } } } From 36e35130337568cd3116e7bbf4804443af7de475 Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Tue, 11 Aug 2026 15:47:27 +0300 Subject: [PATCH 07/12] Remove unnecessary helper --- .../dataflow/ap/ifds/trace/MethodTraceResolver.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt index d71187782..9dfaaed76 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt @@ -78,9 +78,6 @@ class MethodTraceResolver( private val manager: AnalysisUnitRunnerManager get() = runner.manager private val apManager: ApManager get() = runner.apManager - private fun summaryHandler(statement: CommonInst) = - analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) - // Enum can give non-determinacy as its entries have new hash code on every JVM run. // Override hashcode() and equals() when using enum as a field in classes whose objects // can be stored in sets etc. @@ -453,7 +450,7 @@ class MethodTraceResolver( statement: CommonInst, calleeEntry: TraceEntry.MethodEntry ): List { - val handler = summaryHandler(statement) + val handler = analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) val traceEdges = calleeEntry.facts.flatMap { fact -> val mappedFacts = handler.prepareSummaryInitialFact(fact) mappedFacts.map { resolveIntraProceduralTraceEdge(statement, it, includeStatement = false) } @@ -1647,7 +1644,7 @@ class MethodTraceResolver( startFact: MethodCallPrecondition.CallToStartResolved, statement: CommonInst ) { - val summaryHandler = summaryHandler(statement) + val summaryHandler = analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) val resolvedCallSummaries = mutableListOf() val methodSummaries = manager.findFactToFactSummaryEdges(callee, startFact.startFactBase) From 1446613b1f313c3d7b96470666392fa0d7b5a584 Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Tue, 11 Aug 2026 16:22:51 +0300 Subject: [PATCH 08/12] Changes --- .../opentaint/dataflow/ap/ifds/MethodAnalyzer.kt | 9 +++------ .../ap/ifds/MethodAnalyzerEdgeSearcher.kt | 2 +- .../dataflow/ap/ifds/SummaryEdgeSubscription.kt | 16 ++++++++-------- .../ap/ifds/trace/MethodCallPrecondition.kt | 15 ++++++--------- .../ap/ifds/trace/MethodTraceResolver.kt | 2 +- .../go/trace/GoMethodCallPrecondition.kt | 7 +++---- .../ap/ifds/trace/JIRMethodCallPrecondition.kt | 7 +++---- 7 files changed, 25 insertions(+), 33 deletions(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index 6398cb372..8485411a8 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -98,18 +98,15 @@ interface MethodAnalyzer { fun collectStats(stats: MethodStats) data class ZeroToFactSub( - val currentEdge: ZeroToFact, - val methodInitialFactBase: AccessPathBase + val currentEdge: ZeroToFact ) data class FactToFactSub( - val currentEdge: FactToFact, - val methodInitialFactBase: AccessPathBase + val currentEdge: FactToFact ) data class NDFactToFactSub( - val currentEdge: NDFactToFact, - val methodInitialFactBase: AccessPathBase + val currentEdge: NDFactToFact ) fun handleResolvedMethodCall(method: MethodWithContext, handler: MethodCallHandler) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt index 3d2443aeb..44352f148 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzerEdgeSearcher.kt @@ -105,7 +105,7 @@ abstract class MethodAnalyzerEdgeSearcher( ) val preconditions = preconditionFunction.factPrecondition(fact) - return preconditions.queryResult<_, CallPrecondition.Unchanged, PreconditionFactsForInitialFact> { initialFact } + return preconditions.queryResult<_, CallPrecondition.Unchanged, PreconditionFactsForInitialFact> { initialFact } } else { val preconditionFunction = analysisManager.getMethodSequentPrecondition( apManager, analysisContext, statement diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt index 2b639540b..94d7add03 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt @@ -86,7 +86,7 @@ class SummaryEdgeSubscriptionManager( val calleeInitialFactAp = addedSubscription.callerPathEdge.factAp.rebase(addedSubscription.calleeInitialFactBase) val summaries = manager.findFactSummaryEdges(methodEntryPoint, calleeInitialFactAp) - val sub = ZeroToFactSub(addedSubscription.callerPathEdge, addedSubscription.calleeInitialFactBase) + val sub = ZeroToFactSub(addedSubscription.callerPathEdge) if (summaries.isNotEmpty()) { callerAnalyzer.handleZeroToFactMethodSummaryEdge(listOf(sub), summaries) @@ -121,7 +121,7 @@ class SummaryEdgeSubscriptionManager( val calleeInitialFactAp = addedSubscription.callerPathEdge.factAp.rebase(addedSubscription.calleeInitialFactBase) val summaries = manager.findFactSummaryEdges(methodEntryPoint, calleeInitialFactAp) - val sub = FactToFactSub(addedSubscription.callerPathEdge, addedSubscription.calleeInitialFactBase) + val sub = FactToFactSub(addedSubscription.callerPathEdge) if (summaries.isNotEmpty()) { callerAnalyzer.handleFactToFactMethodSummaryEdge(listOf(sub), summaries) @@ -165,7 +165,7 @@ class SummaryEdgeSubscriptionManager( val calleeInitialFactAp = addedSubscription.callerPathEdge.factAp.rebase(addedSubscription.calleeInitialFactBase) val summaries = manager.findFactSummaryEdges(methodEntryPoint, calleeInitialFactAp) - val sub = NDFactToFactSub(addedSubscription.callerPathEdge, addedSubscription.calleeInitialFactBase) + val sub = NDFactToFactSub(addedSubscription.callerPathEdge) if (summaries.isNotEmpty()) { callerAnalyzer.handleNDFactToFactMethodSummaryEdge(listOf(sub), summaries) @@ -568,7 +568,7 @@ class SummaryEdgeSubscriptionManager( ) { subscriptionStorage.findFactEdgeSub(summaryInitialFact).forEach { (ep, subscriptions) -> val summarySubs = subscriptions.mapTo(mutableListOf()) { - FactToFactSub(it.callerPathEdge, it.calleeInitialFactBase) + FactToFactSub(it.callerPathEdge) } if (summarySubs.isEmpty()) return@forEach @@ -579,7 +579,7 @@ class SummaryEdgeSubscriptionManager( subscriptionStorage.findZeroEdgeSub(summaryInitialFact).forEach { (ep, subscriptions) -> val summarySubs = subscriptions.mapTo(mutableListOf()) { - ZeroToFactSub(it.callerPathEdge, it.calleeInitialFactBase) + ZeroToFactSub(it.callerPathEdge) } if (summarySubs.isEmpty()) return@forEach @@ -590,7 +590,7 @@ class SummaryEdgeSubscriptionManager( subscriptionStorage.findFactNDEdgeSub(summaryInitialFact).forEach { (ep, subscriptions) -> val summarySubs = subscriptions.mapTo(mutableListOf()) { - NDFactToFactSub(it.callerPathEdge, it.calleeInitialFactBase) + NDFactToFactSub(it.callerPathEdge) } if (summarySubs.isEmpty()) return@forEach @@ -695,7 +695,7 @@ class SummaryEdgeSubscriptionManager( ) { subscriptionStorage.findFactEdgeSub(seInitialFact).forEach { (ep, subscriptions) -> val summarySubs = subscriptions.mapTo(mutableListOf()) { - FactToFactSub(it.callerPathEdge, it.calleeInitialFactBase) + FactToFactSub(it.callerPathEdge) } if (summarySubs.isEmpty()) return@forEach @@ -706,7 +706,7 @@ class SummaryEdgeSubscriptionManager( subscriptionStorage.findZeroEdgeSub(seInitialFact).forEach { (ep, subscriptions) -> val summarySubs = subscriptions.mapTo(mutableListOf()) { - ZeroToFactSub(it.callerPathEdge, it.calleeInitialFactBase) + ZeroToFactSub(it.callerPathEdge) } if (summarySubs.isEmpty()) return@forEach diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt index 2a0d4f688..2e1b11261 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallPrecondition.kt @@ -14,14 +14,14 @@ import org.opentaint.dataflow.taint.preconditionDnf import org.opentaint.ir.api.common.cfg.CommonInst interface MethodCallPrecondition { - sealed interface CallPrecondition { - data object Unchanged : CallPrecondition + sealed interface CallPrecondition { + data object Unchanged : CallPrecondition } - data class PreconditionFactsForInitialFact( + data class PreconditionFactsForInitialFact( val initialFact: InitialFactAp, - val preconditionFacts: List, - ): CallPrecondition + val preconditionFacts: List, + ): CallPrecondition sealed interface CallPreconditionFact sealed interface CallResolutionPreconditionFact @@ -34,7 +34,7 @@ interface MethodCallPrecondition { data class CallToStart(val callerFact: InitialFactAp, val startFactBase: AccessPathBase) : CallPreconditionFact data class CallToStartResolved(val callerFact: InitialFactAp, val startFactBase: AccessPathBase, val method: MethodWithContext): CallSuccessPreconditionFact - fun factPrecondition(fact: InitialFactAp): List> + fun factPrecondition(fact: InitialFactAp): List fun factPreconditionResolutionFailure(fact: InitialFactAp, startFactBase: AccessPathBase): List fun factPreconditionResolutionSuccess(fact: InitialFactAp, startFactBase: AccessPathBase, method: MethodWithContext): List @@ -85,6 +85,3 @@ interface MethodCallPrecondition { } } -@Suppress("UNCHECKED_CAST") -fun mkUnchanged(): CallPrecondition = - CallPrecondition.Unchanged as CallPrecondition diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt index 9dfaaed76..cab1035b6 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt @@ -902,7 +902,7 @@ class MethodTraceResolver( for (precondition in preconditions) { when (precondition) { is CallPrecondition.Unchanged -> callActions += ActionOrUnchanged.Unchanged(edge) - is PreconditionFactsForInitialFact -> { + is PreconditionFactsForInitialFact -> { val initialEdge = edge.replaceFact(precondition.initialFact) if (!skipFactCheck && !containsEntryEdge(entry.statement, initialEdge)) { continue diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt index 1dfc6d48e..ea1f68f32 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallPrecondition.kt @@ -13,7 +13,6 @@ import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallFailurePr import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallSuccessPreconditionFact import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.PreconditionFactsForInitialFact import org.opentaint.dataflow.ap.ifds.trace.TaintRulePrecondition -import org.opentaint.dataflow.ap.ifds.trace.mkUnchanged import org.opentaint.dataflow.go.GoCallExpr import org.opentaint.dataflow.go.GoFlowFunctionUtils import org.opentaint.dataflow.go.GoFunctionSignature @@ -51,11 +50,11 @@ class GoMethodCallPrecondition( override fun mapExit2Return(fact: InitialFactAp): List = GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) - override fun factPrecondition(fact: InitialFactAp): List> { - val result = mutableListOf>() + override fun factPrecondition(fact: InitialFactAp): List { + val result = mutableListOf() result += preconditionForFact(fact)?.let { PreconditionFactsForInitialFact(fact, it) } - ?: mkUnchanged() + ?: CallPrecondition.Unchanged analysisContext.aliasAnalysis.forEachPossibleAliasAtStatement(statement, fact) { aliasedFact -> preconditionForFact(aliasedFact)?.let { diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt index c336a9747..c8d1921c6 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallPrecondition.kt @@ -13,7 +13,6 @@ import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondit import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallSuccessPreconditionFact import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.PreconditionFactsForInitialFact import org.opentaint.dataflow.ap.ifds.trace.TaintRulePrecondition -import org.opentaint.dataflow.ap.ifds.trace.mkUnchanged import org.opentaint.dataflow.configuration.jvm.TaintMethodSource import org.opentaint.dataflow.configuration.jvm.TaintPassThrough import org.opentaint.dataflow.jvm.ap.ifds.JIRMethodCallFactMapper @@ -44,11 +43,11 @@ class JIRMethodCallPrecondition( ) : MethodCallPrecondition.Default { private val taintCtx get() = analysisContext.taint - override fun factPrecondition(fact: InitialFactAp): List> { - val results = mutableListOf>() + override fun factPrecondition(fact: InitialFactAp): List { + val results = mutableListOf() results += preconditionForFact(fact)?.let { PreconditionFactsForInitialFact(fact, it) } - ?: mkUnchanged() + ?: CallPrecondition.Unchanged analysisContext.aliasAnalysis?.forEachPossibleAliasAtStatement(statement, fact) { aliasedFact -> preconditionForFact(aliasedFact)?.let { results += PreconditionFactsForInitialFact(aliasedFact, it) } From dce130e75c55f0cfebdce1f870e371298c449d44 Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Tue, 11 Aug 2026 17:45:24 +0300 Subject: [PATCH 09/12] Pass callee-entrypoint --- .../dataflow/ap/ifds/MethodAnalyzer.kt | 20 ++++++++++---- .../ap/ifds/TaintAnalysisUnitRunner.kt | 5 ++-- .../ifds/analysis/MethodCallSummaryHandler.kt | 26 +++++++++++-------- .../ap/ifds/trace/MethodTraceResolver.kt | 6 ++--- .../ap/ifds/trace/VulnerabilityChecker.kt | 2 +- .../go/analysis/GoMethodCallSummaryHandler.kt | 7 ++--- .../analysis/JIRMethodCallSummaryHandler.kt | 7 ++--- 7 files changed, 45 insertions(+), 28 deletions(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index 8485411a8..a78e83e72 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -127,7 +127,8 @@ interface MethodAnalyzer { fun resolveCalleeFact( statement: CommonInst, - factAp: FinalFactAp + factAp: FinalFactAp, + callee: MethodEntryPoint, ): Set fun allIntraProceduralFacts(): Map> @@ -1379,9 +1380,13 @@ class NormalMethodAnalyzer( return resolver.resolveForwardTrace(statement, fact, includeStatement, relevantFactFilter) } - override fun resolveCalleeFact(statement: CommonInst, factAp: FinalFactAp): Set = + override fun resolveCalleeFact( + statement: CommonInst, + factAp: FinalFactAp, + callee: MethodEntryPoint, + ): Set = analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) - .prepareSummaryFinalFact(factAp, FactTypeChecker.Dummy) + .prepareSummaryFinalFact(factAp, callee) .toSet() private fun updateTaintRulesStats( @@ -1609,7 +1614,11 @@ class EmptyMethodAnalyzer( TODO("Not yet implemented") } - override fun resolveCalleeFact(statement: CommonInst, factAp: FinalFactAp): Set { + override fun resolveCalleeFact( + statement: CommonInst, + factAp: FinalFactAp, + callee: MethodEntryPoint, + ): Set { TODO("Not yet implemented") } @@ -1878,12 +1887,13 @@ class TimedMethodAnalyzer( override fun resolveCalleeFact( statement: CommonInst, factAp: FinalFactAp, + callee: MethodEntryPoint, ): Set = timeOperation( operation = "resolveCalleeFact", category = OpCategory.TRACE, addToTotalTime = false, ) { - base.resolveCalleeFact(statement, factAp) + base.resolveCalleeFact(statement, factAp, callee) } override fun allIntraProceduralFacts(): Map> = timeOperation( diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/TaintAnalysisUnitRunner.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/TaintAnalysisUnitRunner.kt index 3f53301f6..2a6bfcf64 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/TaintAnalysisUnitRunner.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/TaintAnalysisUnitRunner.kt @@ -506,11 +506,12 @@ class TaintAnalysisUnitRunner( fun resolveCalleeFact( methodEntryPoint: MethodEntryPoint, statement: CommonInst, - factAp: FinalFactAp + factAp: FinalFactAp, + callee: MethodEntryPoint, ): Set { val methodRunners = methodAnalyzers(methodEntryPoint) val runner = methodRunners.getAnalyzer(methodEntryPoint) - return runner.resolveCalleeFact(statement, factAp) + return runner.resolveCalleeFact(statement, factAp, callee) } companion object { diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt index 7cec7b63c..48340146c 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodCallSummaryHandler.kt @@ -34,9 +34,9 @@ interface MethodCallSummaryHandler { ) : SummaryEdge } - fun prepareSummaryInitialFact(fact: InitialFactAp): List + fun prepareSummaryInitialFact(fact: InitialFactAp, callee: MethodEntryPoint): List - fun prepareSummaryFinalFact(fact: FinalFactAp, checker: FactTypeChecker = factTypeChecker): List + fun prepareSummaryFinalFact(fact: FinalFactAp, callee: MethodEntryPoint): List fun handleZeroToZero(summaryFact: FinalFactAp?): Set { if (summaryFact == null) return setOf(Sequent.ZeroToZero) @@ -44,10 +44,12 @@ interface MethodCallSummaryHandler { return setOf(Sequent.ZeroToFact(summaryFact, TraceInfo.ApplySummary)) } - fun prepareZeroToFactSummary(summaryEdge: Edge.ZeroToFact): List = - prepareSummaryFinalFact(summaryEdge.factAp).map { - Edge.ZeroToFact(summaryEdge.methodEntryPoint, summaryEdge.statement, it) + fun prepareZeroToFactSummary(summaryEdge: Edge.ZeroToFact): List { + val callee = summaryEdge.methodEntryPoint + return prepareSummaryFinalFact(summaryEdge.factAp, callee).map { + Edge.ZeroToFact(callee, summaryEdge.statement, it) } + } fun handleZeroToFact( currentFactAp: FinalFactAp, @@ -86,10 +88,11 @@ interface MethodCallSummaryHandler { } fun prepareFactToFactSummary(summaryEdge: Edge.FactToFact): List { - val finalFacts = prepareSummaryFinalFact(summaryEdge.factAp) - return prepareSummaryInitialFact(summaryEdge.initialFactAp).flatMap { initialFactAp -> + val callee = summaryEdge.methodEntryPoint + val finalFacts = prepareSummaryFinalFact(summaryEdge.factAp, callee) + return prepareSummaryInitialFact(summaryEdge.initialFactAp, callee).flatMap { initialFactAp -> finalFacts.map { factAp -> - Edge.FactToFact(summaryEdge.methodEntryPoint, initialFactAp, summaryEdge.statement, factAp) + Edge.FactToFact(callee, initialFactAp, summaryEdge.statement, factAp) } } } @@ -120,13 +123,14 @@ interface MethodCallSummaryHandler { } fun prepareNDFactToFactSummary(summaryEdge: Edge.NDFactToFact): List { - val finalFacts = prepareSummaryFinalFact(summaryEdge.factAp) + val callee = summaryEdge.methodEntryPoint + val finalFacts = prepareSummaryFinalFact(summaryEdge.factAp, callee) return summaryEdge.initialFacts - .map { prepareSummaryInitialFact(it) } + .map { prepareSummaryInitialFact(it, callee) } .cartesianProductMapTo { it.toHashSet() } .flatMap { initialFacts -> finalFacts.map { factAp -> - SummaryEdge.NdF2F(summaryEdge.methodEntryPoint, initialFacts, factAp) + SummaryEdge.NdF2F(callee, initialFacts, factAp) } } } diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt index cab1035b6..96afc15aa 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt @@ -452,7 +452,7 @@ class MethodTraceResolver( ): List { val handler = analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) val traceEdges = calleeEntry.facts.flatMap { fact -> - val mappedFacts = handler.prepareSummaryInitialFact(fact) + val mappedFacts = handler.prepareSummaryInitialFact(fact, calleeEntry.entryPoint) mappedFacts.map { resolveIntraProceduralTraceEdge(statement, it, includeStatement = false) } } @@ -1657,7 +1657,7 @@ class MethodTraceResolver( if (deltas.isEmpty()) continue - val mappedSummaryInitial = summaryHandler.prepareSummaryInitialFact(summaryEdge.initialFactAp) + val mappedSummaryInitial = summaryHandler.prepareSummaryInitialFact(summaryEdge.initialFactAp, callee) for ((matchedEntryFact, delta) in deltas) { // todo: remove this check? @@ -1692,7 +1692,7 @@ class MethodTraceResolver( if (!mappedSummaryFact.contains(callerFact)) continue val mappedSummaryInitialFacts = summaryEdge.initialFacts.map { - summaryHandler.prepareSummaryInitialFact(it) + summaryHandler.prepareSummaryInitialFact(it, callee) } mappedSummaryInitialFacts.cartesianProductMapTo { mappedFactGroup -> diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/VulnerabilityChecker.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/VulnerabilityChecker.kt index 5ad049bad..4aff7100e 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/VulnerabilityChecker.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/VulnerabilityChecker.kt @@ -131,7 +131,7 @@ class VulnerabilityChecker( for (caller in callers) { val callerFacts = manager.withMethodRunner(caller.callerEp) { intraProcCheck.summaries.flatMapTo(hashSetOf()) { - resolveCalleeFact(caller.callerEp, caller.statement, it) + resolveCalleeFact(caller.callerEp, caller.statement, it, request.ep) } } callerFacts.mapTo(unprocessed) { diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt index e11bc9489..6f37f4b92 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodCallSummaryHandler.kt @@ -3,6 +3,7 @@ package org.opentaint.dataflow.go.analysis import org.opentaint.dataflow.ap.ifds.Edge import org.opentaint.dataflow.ap.ifds.ExclusionSet import org.opentaint.dataflow.ap.ifds.FactTypeChecker +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp @@ -25,12 +26,12 @@ class GoMethodCallSummaryHandler( ) : MethodCallSummaryHandler { override val factTypeChecker: FactTypeChecker = FactTypeChecker.Dummy - override fun prepareSummaryInitialFact(fact: InitialFactAp): List { + override fun prepareSummaryInitialFact(fact: InitialFactAp, callee: MethodEntryPoint): List { return GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) } - override fun prepareSummaryFinalFact(fact: FinalFactAp, checker: FactTypeChecker): List { - return GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, checker) + override fun prepareSummaryFinalFact(fact: FinalFactAp, callee: MethodEntryPoint): List { + return GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, factTypeChecker) } private val callExpr: GoCallExpr by lazy { diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt index ee692a875..b01c3d42d 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodCallSummaryHandler.kt @@ -3,6 +3,7 @@ package org.opentaint.dataflow.jvm.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.Edge import org.opentaint.dataflow.ap.ifds.ExclusionSet import org.opentaint.dataflow.ap.ifds.FactTypeChecker +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp @@ -24,11 +25,11 @@ class JIRMethodCallSummaryHandler( JIRMethodCallRuleBasedSummaryRewriter(statement, analysisContext, apManager) } - override fun prepareSummaryInitialFact(fact: InitialFactAp): List = + override fun prepareSummaryInitialFact(fact: InitialFactAp, callee: MethodEntryPoint): List = JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) - override fun prepareSummaryFinalFact(fact: FinalFactAp, checker: FactTypeChecker): List = - JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, checker) + override fun prepareSummaryFinalFact(fact: FinalFactAp, callee: MethodEntryPoint): List = + JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact, factTypeChecker) override fun handleZeroToZero(summaryFact: FinalFactAp?): Set = super.handleZeroToZero(summaryFact).flatMapTo(hashSetOf()) { seq -> From a187a7d6434c821d1de1c1a0df4106d8d82c42fe Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Wed, 12 Aug 2026 16:06:00 +0300 Subject: [PATCH 10/12] Fix ellipsis test --- .../RuleWithEllipsisMethodInvocation.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/core/opentaint-java-querylang/samples/src/main/java/example/RuleWithEllipsisMethodInvocation.java b/core/opentaint-java-querylang/samples/src/main/java/example/RuleWithEllipsisMethodInvocation.java index bafa6e8ef..378f5f593 100644 --- a/core/opentaint-java-querylang/samples/src/main/java/example/RuleWithEllipsisMethodInvocation.java +++ b/core/opentaint-java-querylang/samples/src/main/java/example/RuleWithEllipsisMethodInvocation.java @@ -6,7 +6,7 @@ @RuleSet("example/RuleWithEllipsisMethodInvocation.yaml") public abstract class RuleWithEllipsisMethodInvocation implements RuleSample { Inner src() { - return new Inner(new Object()); + return new Inner(new Inner2()); } void sink(String data) {} @@ -15,7 +15,7 @@ final static class PositiveOneCall extends RuleWithEllipsisMethodInvocation { @Override public void entrypoint() { Inner data = src(); - String str = data.getObjGood().toString(); + String str = data.getInner().toString(); sink(str); } } @@ -33,19 +33,27 @@ final static class NegativeTwoCalls extends RuleWithEllipsisMethodInvocation { @Override public void entrypoint() { Inner data = src(); - String str = data.getObjGood().getClass().toString(); + String str = data.getInner().getObjGood().toString(); sink(str); } } + private static final class Inner2 { + final private Object obj = new Object(); + + public Object getObjGood() { + return obj; + } + } + static final private class Inner { - final private Object obj; + final private Inner2 obj; - public Inner(Object obj) { + public Inner(Inner2 obj) { this.obj = obj; } - public Object getObjGood() { + public Inner2 getInner() { return obj; } } From 0ef9583207d781f9d7cbc0a84e9ff7a370f27542 Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Fri, 14 Aug 2026 16:43:39 +0300 Subject: [PATCH 11/12] Introduce call summary precondition --- .../dataflow/ap/ifds/analysis/AnalysisManager.kt | 7 +++++++ .../ap/ifds/trace/MethodCallSummaryPrecondition.kt | 8 ++++++++ .../dataflow/ap/ifds/trace/MethodTraceResolver.kt | 10 +++++----- .../dataflow/go/analysis/GoAnalysisManager.kt | 10 ++++++++++ .../go/trace/GoMethodCallSummaryPrecondition.kt | 14 ++++++++++++++ .../jvm/ap/ifds/analysis/JIRAnalysisManager.kt | 11 +++++++++++ .../ifds/trace/JIRMethodCallSummaryPrecondition.kt | 14 ++++++++++++++ 7 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPrecondition.kt create mode 100644 core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPrecondition.kt create mode 100644 core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPrecondition.kt diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt index c11decfd2..eddb2b54b 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/AnalysisManager.kt @@ -10,6 +10,7 @@ import org.opentaint.dataflow.ap.ifds.TaintAnalysisUnitRunner import org.opentaint.dataflow.ap.ifds.access.ApManager import org.opentaint.dataflow.ap.ifds.access.FinalFactAp import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition import org.opentaint.dataflow.ap.ifds.trace.MethodStartPrecondition import org.opentaint.dataflow.graph.MethodInstGraph @@ -90,6 +91,12 @@ interface AnalysisManager: LanguageManager { statement: CommonInst, ): MethodCallSummaryHandler + fun getMethodCallSummaryPrecondition( + apManager: ApManager, + analysisContext: MethodAnalysisContext, + statement: CommonInst, + ): MethodCallSummaryPrecondition + fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPrecondition.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPrecondition.kt new file mode 100644 index 000000000..c2e1e0587 --- /dev/null +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodCallSummaryPrecondition.kt @@ -0,0 +1,8 @@ +package org.opentaint.dataflow.ap.ifds.trace + +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.access.InitialFactAp + +interface MethodCallSummaryPrecondition { + fun callSummaryPrecondition(fact: InitialFactAp, callee: MethodEntryPoint): List +} diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt index 96afc15aa..7b77075e1 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/trace/MethodTraceResolver.kt @@ -450,9 +450,9 @@ class MethodTraceResolver( statement: CommonInst, calleeEntry: TraceEntry.MethodEntry ): List { - val handler = analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) + val handler = analysisManager.getMethodCallSummaryPrecondition(apManager, analysisContext, statement) val traceEdges = calleeEntry.facts.flatMap { fact -> - val mappedFacts = handler.prepareSummaryInitialFact(fact, calleeEntry.entryPoint) + val mappedFacts = handler.callSummaryPrecondition(fact, calleeEntry.entryPoint) mappedFacts.map { resolveIntraProceduralTraceEdge(statement, it, includeStatement = false) } } @@ -1644,7 +1644,7 @@ class MethodTraceResolver( startFact: MethodCallPrecondition.CallToStartResolved, statement: CommonInst ) { - val summaryHandler = analysisManager.getMethodCallSummaryHandler(apManager, analysisContext, statement) + val handler = analysisManager.getMethodCallSummaryPrecondition(apManager, analysisContext, statement) val resolvedCallSummaries = mutableListOf() val methodSummaries = manager.findFactToFactSummaryEdges(callee, startFact.startFactBase) @@ -1657,7 +1657,7 @@ class MethodTraceResolver( if (deltas.isEmpty()) continue - val mappedSummaryInitial = summaryHandler.prepareSummaryInitialFact(summaryEdge.initialFactAp, callee) + val mappedSummaryInitial = handler.callSummaryPrecondition(summaryEdge.initialFactAp, callee) for ((matchedEntryFact, delta) in deltas) { // todo: remove this check? @@ -1692,7 +1692,7 @@ class MethodTraceResolver( if (!mappedSummaryFact.contains(callerFact)) continue val mappedSummaryInitialFacts = summaryEdge.initialFacts.map { - summaryHandler.prepareSummaryInitialFact(it, callee) + handler.callSummaryPrecondition(it, callee) } mappedSummaryInitialFacts.cartesianProductMapTo { mappedFactGroup -> diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt index ca17f100e..8e84544f0 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt @@ -44,6 +44,8 @@ import org.opentaint.ir.go.inst.GoIRInst import org.opentaint.util.analysis.ApplicationGraph import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPrecondition +import org.opentaint.dataflow.go.trace.GoMethodCallSummaryPrecondition /** * Central factory that wires all Go dataflow analysis components together. @@ -158,6 +160,14 @@ class GoAnalysisManager( ) } + override fun getMethodCallSummaryPrecondition( + apManager: ApManager, + analysisContext: MethodAnalysisContext, + statement: CommonInst + ): MethodCallSummaryPrecondition { + return GoMethodCallSummaryPrecondition(statement as GoIRInst) + } + override fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPrecondition.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPrecondition.kt new file mode 100644 index 000000000..7d46f5e73 --- /dev/null +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/trace/GoMethodCallSummaryPrecondition.kt @@ -0,0 +1,14 @@ +package org.opentaint.dataflow.go.trace + +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.access.InitialFactAp +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPrecondition +import org.opentaint.dataflow.go.GoMethodCallFactMapper +import org.opentaint.ir.go.inst.GoIRInst + +class GoMethodCallSummaryPrecondition( + private val statement: GoIRInst, +) : MethodCallSummaryPrecondition { + override fun callSummaryPrecondition(fact: InitialFactAp, callee: MethodEntryPoint): List = + GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) +} diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt index 98f615535..ea659af78 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt @@ -52,6 +52,8 @@ import org.opentaint.jvm.graph.JApplicationGraph import org.opentaint.util.analysis.ApplicationGraph import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPrecondition +import org.opentaint.dataflow.jvm.ap.ifds.trace.JIRMethodCallSummaryPrecondition class JIRAnalysisManager( cp: JIRClasspath, @@ -236,6 +238,15 @@ class JIRAnalysisManager( } } + override fun getMethodCallSummaryPrecondition( + apManager: ApManager, + analysisContext: MethodAnalysisContext, + statement: CommonInst + ): MethodCallSummaryPrecondition { + jIRDowncast(statement) + return JIRMethodCallSummaryPrecondition(statement) + } + override fun getMethodSideEffectSummaryHandler( apManager: ApManager, analysisContext: MethodAnalysisContext, diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPrecondition.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPrecondition.kt new file mode 100644 index 000000000..19c2efa61 --- /dev/null +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/trace/JIRMethodCallSummaryPrecondition.kt @@ -0,0 +1,14 @@ +package org.opentaint.dataflow.jvm.ap.ifds.trace + +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint +import org.opentaint.dataflow.ap.ifds.access.InitialFactAp +import org.opentaint.dataflow.ap.ifds.trace.MethodCallSummaryPrecondition +import org.opentaint.dataflow.jvm.ap.ifds.JIRMethodCallFactMapper +import org.opentaint.ir.api.jvm.cfg.JIRInst + +class JIRMethodCallSummaryPrecondition( + private val statement: JIRInst, +) : MethodCallSummaryPrecondition { + override fun callSummaryPrecondition(fact: InitialFactAp, callee: MethodEntryPoint): List = + JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, fact) +} From e5bddcfd2146b8ec078a40ce194f3fee44bf5359 Mon Sep 17 00:00:00 2001 From: Pavel Balay Date: Fri, 14 Aug 2026 17:59:28 +0300 Subject: [PATCH 12/12] Refactor summary application --- .../dataflow/ap/ifds/MethodAnalyzer.kt | 57 ++++++++++++++----- .../ap/ifds/SummaryEdgeSubscription.kt | 11 ++-- .../MethodSideEffectSummaryHandler.kt | 5 +- .../dataflow/go/analysis/GoAnalysisManager.kt | 2 +- .../go/analysis/GoMethodSideEffectHandler.kt | 12 +--- .../ap/ifds/analysis/JIRAnalysisManager.kt | 2 +- .../analysis/JIRMethodSideEffectHandler.kt | 12 +--- 7 files changed, 55 insertions(+), 46 deletions(-) diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt index a78e83e72..253feaab4 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/MethodAnalyzer.kt @@ -69,7 +69,7 @@ interface MethodAnalyzer { fun handleMethodSideEffectRequirement( currentEdge: FactToFact, - methodInitialFactBase: AccessPathBase, + callee: MethodEntryPoint, methodSideEffectRequirements: List ) @@ -80,11 +80,13 @@ interface MethodAnalyzer { fun handleZeroToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List ) fun handleFactToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List ) @@ -881,14 +883,21 @@ class NormalMethodAnalyzer( override fun handleMethodSideEffectRequirement( currentEdge: FactToFact, - methodInitialFactBase: AccessPathBase, + callee: MethodEntryPoint, methodSideEffectRequirements: List ) { - val methodInitialFact = currentEdge.factAp.rebase(methodInitialFactBase) - val exclusionRefinements = methodSideEffectRequirements.mapNotNull { methodSinkRequirement -> - MethodSummaryEdgeApplicationUtils.emptyDeltaExclusionRefinementOrNull( - methodInitialFact, methodSinkRequirement - ) + val summaryHandler = analysisManager.getMethodCallSummaryHandler( + apManager, analysisContext, currentEdge.statement + ) + + val exclusionRefinements = mutableListOf() + methodSideEffectRequirements.forEach { methodSinkRequirement -> + val mappedRequirements = summaryHandler.prepareSummaryInitialFact(methodSinkRequirement, callee) + mappedRequirements.mapNotNullTo(exclusionRefinements) { mappedRequirement -> + MethodSummaryEdgeApplicationUtils.emptyDeltaExclusionRefinementOrNull( + currentEdge.factAp, mappedRequirement + ) + } } if (exclusionRefinements.isEmpty()) { @@ -920,6 +929,7 @@ class NormalMethodAnalyzer( override fun handleZeroToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List ) { for (sub in summarySubs) { @@ -930,8 +940,15 @@ class NormalMethodAnalyzer( sub.currentEdge.statement, runner ) + val summaryHandler = analysisManager.getMethodCallSummaryHandler( + apManager, analysisContext, sub.currentEdge.statement + ) - val summariesToApply = sideEffectSummaries.flatMap { handler.prepareSideEffectSummary(it) } + val summariesToApply = sideEffectSummaries.flatMap { se -> + summaryHandler.prepareSummaryInitialFact(se.initialFactAp, callee).map { mappedInitialFact -> + SideEffectSummary.FactSideEffectSummary(mappedInitialFact, se.kind) + } + } applyMethodSideEffectSummaries( currentEdge = sub.currentEdge, @@ -944,6 +961,7 @@ class NormalMethodAnalyzer( override fun handleFactToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List ) { for (sub in summarySubs) { @@ -954,8 +972,15 @@ class NormalMethodAnalyzer( sub.currentEdge.statement, runner, ) + val summaryHandler = analysisManager.getMethodCallSummaryHandler( + apManager, analysisContext, sub.currentEdge.statement + ) - val summariesToApply = sideEffectSummaries.flatMap { handler.prepareSideEffectSummary(it) } + val summariesToApply = sideEffectSummaries.flatMap { se -> + summaryHandler.prepareSummaryInitialFact(se.initialFactAp, callee).map { mappedInitialFact -> + SideEffectSummary.FactSideEffectSummary(mappedInitialFact, se.kind) + } + } applyMethodSideEffectSummaries( currentEdge = sub.currentEdge, @@ -1559,7 +1584,7 @@ class EmptyMethodAnalyzer( override fun handleMethodSideEffectRequirement( currentEdge: FactToFact, - methodInitialFactBase: AccessPathBase, + callee: MethodEntryPoint, methodSideEffectRequirements: List ) { error("Empty method should not receive side effect requirements") @@ -1574,6 +1599,7 @@ class EmptyMethodAnalyzer( override fun handleZeroToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List ) { error("Empty method should not receive side effects") @@ -1581,6 +1607,7 @@ class EmptyMethodAnalyzer( override fun handleFactToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List ) { error("Empty method should not receive side effects") @@ -1803,13 +1830,13 @@ class TimedMethodAnalyzer( override fun handleMethodSideEffectRequirement( currentEdge: FactToFact, - methodInitialFactBase: AccessPathBase, + callee: MethodEntryPoint, methodSideEffectRequirements: List, ) = timeOperation( operation = "handleMethodSideEffectRequirement", category = OpCategory.SUMMARY, ) { - base.handleMethodSideEffectRequirement(currentEdge, methodInitialFactBase, methodSideEffectRequirements) + base.handleMethodSideEffectRequirement(currentEdge, callee, methodSideEffectRequirements) } override fun handleZeroToZeroMethodSideEffectSummary( @@ -1824,22 +1851,24 @@ class TimedMethodAnalyzer( override fun handleZeroToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List, ) = timeOperation( operation = "handleZeroToFactMethodSideEffectSummary", category = OpCategory.SUMMARY, ) { - base.handleZeroToFactMethodSideEffectSummary(summarySubs, sideEffectSummaries) + base.handleZeroToFactMethodSideEffectSummary(summarySubs, callee, sideEffectSummaries) } override fun handleFactToFactMethodSideEffectSummary( summarySubs: List, + callee: MethodEntryPoint, sideEffectSummaries: List, ) = timeOperation( operation = "handleFactToFactMethodSideEffectSummary", category = OpCategory.SUMMARY, ) { - base.handleFactToFactMethodSideEffectSummary(summarySubs, sideEffectSummaries) + base.handleFactToFactMethodSideEffectSummary(summarySubs, callee, sideEffectSummaries) } override fun handleNDFactToFactMethodSideEffectSummary( diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt index 94d7add03..716514f3a 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/SummaryEdgeSubscription.kt @@ -101,6 +101,7 @@ class SummaryEdgeSubscriptionManager( if (sideEffectSummaries.isNotEmpty()) { callerAnalyzer.handleZeroToFactMethodSideEffectSummary( listOf(sub), + methodEntryPoint, sideEffectSummaries ) } @@ -136,7 +137,7 @@ class SummaryEdgeSubscriptionManager( if (sideEffectRequirements.isNotEmpty()) { callerAnalyzer.handleMethodSideEffectRequirement( addedSubscription.callerPathEdge, - addedSubscription.calleeInitialFactBase, + methodEntryPoint, sideEffectRequirements ) } @@ -145,6 +146,7 @@ class SummaryEdgeSubscriptionManager( if (sideEffectSummaries.isNotEmpty()) { callerAnalyzer.handleFactToFactMethodSideEffectSummary( listOf(sub), + methodEntryPoint, sideEffectSummaries ) } @@ -634,7 +636,8 @@ class SummaryEdgeSubscriptionManager( val analyzer = processingCtx.getMethodAnalyzer(ep) for (subscription in subscriptions) { analyzer.handleMethodSideEffectRequirement( - subscription.callerPathEdge, subscription.calleeInitialFactBase, + subscription.callerPathEdge, + methodEntryPoint, listOf(sideEffectRequirement) ) } @@ -701,7 +704,7 @@ class SummaryEdgeSubscriptionManager( if (summarySubs.isEmpty()) return@forEach val analyzer = processingCtx.getMethodAnalyzer(ep) - analyzer.handleFactToFactMethodSideEffectSummary(summarySubs, sideEffects) + analyzer.handleFactToFactMethodSideEffectSummary(summarySubs, methodEntryPoint, sideEffects) } subscriptionStorage.findZeroEdgeSub(seInitialFact).forEach { (ep, subscriptions) -> @@ -712,7 +715,7 @@ class SummaryEdgeSubscriptionManager( if (summarySubs.isEmpty()) return@forEach val analyzer = processingCtx.getMethodAnalyzer(ep) - analyzer.handleZeroToFactMethodSideEffectSummary(summarySubs, sideEffects) + analyzer.handleZeroToFactMethodSideEffectSummary(summarySubs, methodEntryPoint, sideEffects) } } } diff --git a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt index a831d97e2..14ab9371a 100644 --- a/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-dataflow/src/main/kotlin/org/opentaint/dataflow/ap/ifds/analysis/MethodSideEffectSummaryHandler.kt @@ -1,6 +1,7 @@ package org.opentaint.dataflow.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.ExclusionSet +import org.opentaint.dataflow.ap.ifds.MethodEntryPoint import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils.SummaryEdgeApplication import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils.SummaryEdgeApplication.SummaryApRefinement import org.opentaint.dataflow.ap.ifds.MethodSummaryEdgeApplicationUtils.SummaryEdgeApplication.SummaryExclusionRefinement @@ -11,10 +12,6 @@ import org.opentaint.dataflow.ap.ifds.access.InitialFactAp import org.opentaint.dataflow.ap.ifds.analysis.MethodSequentFlowFunction.Sequent interface MethodSideEffectSummaryHandler { - fun prepareSideEffectSummary( - sideEffectSummary: SideEffectSummary.FactSideEffectSummary, - ): List - fun handleZeroToZero( sideEffects: List, ): Set = emptySet() diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt index 8e84544f0..9b588ebea 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoAnalysisManager.kt @@ -174,7 +174,7 @@ class GoAnalysisManager( statement: CommonInst, runner: AnalysisRunner, ): MethodSideEffectSummaryHandler { - return GoMethodSideEffectHandler(statement as GoIRInst, runner) + return GoMethodSideEffectHandler(runner) } override fun getMethodStartPrecondition( diff --git a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt index c913073c5..bf0fdd230 100644 --- a/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-go-dataflow/src/main/kotlin/org/opentaint/dataflow/go/analysis/GoMethodSideEffectHandler.kt @@ -1,18 +1,8 @@ package org.opentaint.dataflow.go.analysis import org.opentaint.dataflow.ap.ifds.AnalysisRunner -import org.opentaint.dataflow.ap.ifds.SideEffectSummary -import org.opentaint.dataflow.go.GoMethodCallFactMapper import org.opentaint.dataflow.taint.MethodSideEffectHandlerWithAnyAccessorRequestHandling -import org.opentaint.ir.go.inst.GoIRInst class GoMethodSideEffectHandler( - private val statement: GoIRInst, override val runner: AnalysisRunner -) : MethodSideEffectHandlerWithAnyAccessorRequestHandling { - override fun prepareSideEffectSummary( - sideEffectSummary: SideEffectSummary.FactSideEffectSummary, - ): List = - GoMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, sideEffectSummary.initialFactAp) - .map { sideEffectSummary.copy(initialFactAp = it) } -} +) : MethodSideEffectHandlerWithAnyAccessorRequestHandling diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt index ea659af78..2dbb0b260 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRAnalysisManager.kt @@ -256,7 +256,7 @@ class JIRAnalysisManager( jIRDowncast(statement) jIRDowncast(analysisContext) - return JIRMethodSideEffectHandler(statement, runner) + return JIRMethodSideEffectHandler(runner) } override fun getMethodCallPrecondition( diff --git a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt index 66ac0a281..0ad1697d5 100644 --- a/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt +++ b/core/opentaint-dataflow-core/opentaint-jvm-dataflow/src/main/kotlin/org/opentaint/dataflow/jvm/ap/ifds/analysis/JIRMethodSideEffectHandler.kt @@ -1,18 +1,8 @@ package org.opentaint.dataflow.jvm.ap.ifds.analysis import org.opentaint.dataflow.ap.ifds.AnalysisRunner -import org.opentaint.dataflow.ap.ifds.SideEffectSummary -import org.opentaint.dataflow.jvm.ap.ifds.JIRMethodCallFactMapper import org.opentaint.dataflow.taint.MethodSideEffectHandlerWithAnyAccessorRequestHandling -import org.opentaint.ir.api.jvm.cfg.JIRInst class JIRMethodSideEffectHandler( - private val statement: JIRInst, override val runner: AnalysisRunner -) : MethodSideEffectHandlerWithAnyAccessorRequestHandling { - override fun prepareSideEffectSummary( - sideEffectSummary: SideEffectSummary.FactSideEffectSummary, - ): List = - JIRMethodCallFactMapper.mapMethodExitToReturnFlowFact(statement, sideEffectSummary.initialFactAp) - .map { sideEffectSummary.copy(initialFactAp = it) } -} +) : MethodSideEffectHandlerWithAnyAccessorRequestHandling