Skip to content

Commit 64aebe7

Browse files
committed
Simplify detector
1 parent d747447 commit 64aebe7

File tree

2 files changed

+28
-32
lines changed

2 files changed

+28
-32
lines changed

usvm-ts/src/main/kotlin/org/usvm/api/checkers/UnreachableCodeDetector.kt

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,41 @@ import org.usvm.machine.interpreter.TsStepScope
99
import org.usvm.machine.state.TsState
1010
import org.usvm.statistics.UMachineObserver
1111

12+
data class UncoveredIfSuccessors(val ifStmt: EtsIfStmt, val successors: Set<EtsStmt>)
13+
1214
class 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
}

usvm-ts/src/test/kotlin/org/usvm/samples/checkers/UnreachableCodeDetector.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import org.jacodb.ets.base.EtsAssignStmt
44
import org.jacodb.ets.base.EtsIfStmt
55
import org.jacodb.ets.model.EtsScene
66
import org.jacodb.ets.utils.loadEtsFileAutoConvert
7-
import org.jacodb.ets.utils.loadEtsProjectFromIR
87
import org.junit.jupiter.api.Test
98
import org.usvm.UMachineOptions
109
import org.usvm.api.checkers.UnreachableCodeDetector
@@ -52,7 +51,7 @@ class UnreachableCodeDetectorTest {
5251
machine.analyze(methods)
5352

5453
val results = observer.result.values.singleOrNull() ?: error("No results found")
55-
check(results.single().second.single() is EtsAssignStmt)
54+
check(results.single().successors.single() is EtsAssignStmt)
5655
}
5756

5857
@Test
@@ -73,6 +72,6 @@ class UnreachableCodeDetectorTest {
7372

7473
val relatedBranch = results.single { it.key.name == methodName }
7574
val stmts = relatedBranch.value.single()
76-
check(stmts.second.single() is EtsIfStmt)
75+
check(stmts.successors.single() is EtsIfStmt)
7776
}
7877
}

0 commit comments

Comments
 (0)