@@ -9,44 +9,41 @@ import org.usvm.machine.interpreter.TsStepScope
99import org.usvm.machine.state.TsState
1010import org.usvm.statistics.UMachineObserver
1111
12+ data class UncoveredIfSuccessors (val ifStmt : EtsIfStmt , val successors : Set <EtsStmt >)
13+
1214class UnreachableCodeDetector : TsInterpreterObserver , UMachineObserver <TsState > {
13- private val uncoveredIfSuccessors = hashMapOf<EtsMethod , MutableSet <EtsStmt >>()
14- private val allIfSuccessors = hashMapOf<EtsMethod , MutableSet <EtsStmt >>()
15- private val visitedIfStmt = hashMapOf<EtsMethod , MutableSet <EtsIfStmt >>()
16-
17- lateinit var result: Map <EtsMethod , Set <Pair <EtsIfStmt , Set <EtsStmt >>>>
18-
19- override fun onStatePeeked (state : TsState ) {
20- val method = state.currentStatement.method
21- if (method !in allIfSuccessors) {
22- val ifSuccessors = method.cfg.stmts
23- .filter { it is EtsIfStmt }
24- .flatMapTo(hashSetOf()) { method.cfg.successors(it) }
25- allIfSuccessors[method] = ifSuccessors
26- uncoveredIfSuccessors[method] = ifSuccessors.toHashSet()
27- }
28- }
15+ private val uncoveredSuccessorsOfVisitedIfStmts = hashMapOf<EtsMethod , MutableMap <EtsIfStmt , MutableSet <EtsStmt >>>()
16+ lateinit var result: Map <EtsMethod , List <UncoveredIfSuccessors >>
2917
3018 override fun onIfStatement (simpleValueResolver : TsSimpleValueResolver , stmt : EtsIfStmt , scope : TsStepScope ) {
31- visitedIfStmt.getOrPut(stmt.method) { hashSetOf() }.add(stmt)
19+ val ifStmts = uncoveredSuccessorsOfVisitedIfStmts.getOrPut(stmt.method) { mutableMapOf () }
20+ // We've already added its successors in the map
21+ if (stmt in ifStmts) return
22+
23+ val successors = stmt.method.cfg.successors(stmt)
24+ ifStmts[stmt] = successors.toMutableSet()
3225 }
3326
3427 override fun onState (parent : TsState , forks : Sequence <TsState >) {
35- if (parent.pathNode.parent?.statement !is EtsIfStmt ) return
28+ val previousStatement = parent.pathNode.parent?.statement
29+ if (previousStatement !is EtsIfStmt ) return
30+
31+ val method = parent.currentStatement.method
32+ val remainingUncoveredIfSuccessors = uncoveredSuccessorsOfVisitedIfStmts.getValue(method)
33+ val remainingSuccessorsForCurrentIf = remainingUncoveredIfSuccessors[previousStatement]
34+ ? : return // No uncovered successors for this if statement
3635
37- val currentIfSuccessors = uncoveredIfSuccessors.getValue(parent.currentStatement.method)
38- currentIfSuccessors - = parent.currentStatement
39- forks.forEach { currentIfSuccessors - = it.currentStatement }
36+ remainingSuccessorsForCurrentIf - = parent.currentStatement
37+ forks.forEach { remainingSuccessorsForCurrentIf - = it.currentStatement }
4038 }
4139
4240 override fun onMachineStopped () {
43- result = uncoveredIfSuccessors.mapNotNull { (method, values) ->
44- val visitedIfs = visitedIfStmt[method] ? : return @mapNotNull null
45- val grouped = values.groupBy { method.cfg.predecessors(it).single() }
46- .map { it.key as EtsIfStmt to it.value.toSet() }
47- .filter { it.first in visitedIfs }
48- .toSet()
49- method to grouped
50- }.toMap()
41+ result = uncoveredSuccessorsOfVisitedIfStmts
42+ .mapNotNull { (method, uncoveredIfSuccessors) ->
43+ uncoveredIfSuccessors
44+ .filter { it.value.isNotEmpty() }
45+ .takeIf { it.isNotEmpty() }
46+ ?.let { method to it.map { UncoveredIfSuccessors (it.key, it.value) } }
47+ }.toMap()
5148 }
5249}
0 commit comments