Skip to content

Commit

Permalink
Support "unknown chunks" (null)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lipen committed May 17, 2024
1 parent 05a1e00 commit 1b5872c
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ fun <Message> randomRouter(
RandomRouter(size, random, routeeSpawnOptions, routeeFactory)
}

fun <Message, Key> messageKeyRouter(
keyExtractor: (Message) -> Key,
fun <Message, Key : Any> messageKeyRouter(
keyExtractor: (Message) -> Key?,
routeeNameFactory: (Key) -> String = { it.toString() },
routeeSpawnOptions: SpawnOptions = SpawnOptions.default,
routeeFactory: KeyRouteeFactory<Message, Key>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ import org.jacodb.actors.api.options.SpawnOptions
internal typealias KeyRouteeFactory<Message, Key> = ActorContext<Message>.(Key) -> Actor<Message>

context(ActorContext<Message>)
internal class MessageKeyRouter<Message, Key>(
private val keyExtractor: (Message) -> Key,
internal class MessageKeyRouter<Message, Key : Any>(
private val keyExtractor: (Message) -> Key?,
private val routeeNameFactory: (Key) -> String,
private val routeeSpawnOptions: SpawnOptions,
private val routeeFactory: KeyRouteeFactory<Message, Key>,
) : Actor<Message> {
private val routees = hashMapOf<Key, ActorRef<Message>>()

override suspend fun receive(message: Message) {
val key = keyExtractor(message)
val key = keyExtractor(message) ?: return
val routee = routees.computeIfAbsent(key) {
val name = routeeNameFactory(key)
spawn(name, routeeSpawnOptions) { routeeFactory(key) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,5 @@ import org.jacodb.analysis.ifds.domain.Chunk
import org.jacodb.analysis.ifds.messages.RunnerMessage

fun interface ChunkResolver {
fun chunkByMessage(message: RunnerMessage): Chunk
fun chunkByMessage(message: RunnerMessage): Chunk?
}

fun interface ChunkStrategy<Stmt> {
fun chunkByStmt(stmt: Stmt): Chunk
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2022 UnitTestBot contributors (utbot.org)
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.jacodb.analysis.ifds

import org.jacodb.analysis.ifds.domain.Chunk

fun interface ChunkStrategy<Stmt> {
fun chunkByStmt(stmt: Stmt): Chunk?
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.jacodb.analysis.ifds.messages.RunnerMessage
interface IfdsContext<Stmt> {
val options: IfdsSystemOptions

fun chunkByMessage(message: RunnerMessage): Chunk
fun chunkByMessage(message: RunnerMessage): Chunk?
fun runnerIdByMessage(message: RunnerMessage): RunnerId

fun getAnalyzer(runnerId: RunnerId): Analyzer<Stmt, *>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class JcChunkResolver(
private val chunkStrategy: org.jacodb.analysis.ifds.ChunkStrategy<JcInst>,
) : ChunkResolver {
@Suppress("UNCHECKED_CAST")
override fun chunkByMessage(message: RunnerMessage): Chunk =
override fun chunkByMessage(message: RunnerMessage): Chunk? =
when (message) {
is AnalyzerMessage<*, *> -> {
when (message) {
Expand Down Expand Up @@ -122,4 +122,4 @@ class JcChunkResolver(
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.jacodb.analysis.ifds.common

import org.jacodb.analysis.ifds.ChunkResolver
import org.jacodb.analysis.ifds.ChunkStrategy
import org.jacodb.analysis.ifds.IfdsContext
import org.jacodb.analysis.ifds.IfdsSystemOptions
import org.jacodb.analysis.ifds.domain.Chunk
Expand All @@ -32,11 +33,12 @@ class JcIfdsContext<Fact>(
private val cp: JcClasspath,
override val options: IfdsSystemOptions,
private val bannedPackagePrefixes: List<String>,
private val chunkStrategy: ChunkResolver,
val strategy: ChunkStrategy<JcInst>,
private val resolver: ChunkResolver,
private val analyzerFactory: (RunnerId) -> JcBaseAnalyzer<Fact>,
) : IfdsContext<JcInst> {
override fun chunkByMessage(message: RunnerMessage): Chunk =
chunkStrategy.chunkByMessage(message)
override fun chunkByMessage(message: RunnerMessage): Chunk? =
resolver.chunkByMessage(message)

override fun runnerIdByMessage(message: RunnerMessage): RunnerId =
message.runnerId
Expand All @@ -47,5 +49,5 @@ class JcIfdsContext<Fact>(
analyzers.computeIfAbsent(runnerId, analyzerFactory)

override fun getIndirectionHandler(runnerId: RunnerId): IndirectionHandler =
JcIndirectionHandler(HierarchyExtensionImpl(cp), bannedPackagePrefixes, runnerId)
JcIndirectionHandler(HierarchyExtensionImpl(cp), bannedPackagePrefixes, runnerId, this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,35 @@ class JcIndirectionHandler(
private val hierarchy: HierarchyExtension,
private val bannedPackagePrefixes: List<String>,
private val runnerId: RunnerId,
private val context: JcIfdsContext<*>,
) : IndirectionHandler {
private val cache = hashMapOf<JcMethod, List<JcMethod>>()

override fun handle(message: IndirectionMessage): Collection<RunnerMessage> {
val result = handleEx(message)
if (result.size == 1 && result.single() is NoResolvedCall<*, *>) {
return result
}

if (result.isEmpty()) return result

val calls = result.filterIsInstance<ResolvedCall<*, *, *>>()
val allowedCalls = calls.filter {
val method = it.method as JcMethod
val stmt = method.instList.firstOrNull() ?: return@filter false

context.strategy.chunkByStmt(stmt) != null
}

if (allowedCalls.isEmpty()) {
val proto = calls.first()
return listOf(NoResolvedCall(proto.runnerId, proto.edge))
}

return allowedCalls
}

private fun handleEx(message: IndirectionMessage): Collection<RunnerMessage> {
@Suppress("UNCHECKED_CAST")
message as? UnresolvedCall<JcInst, TaintDomainFact> ?: error("Unexpected message: $message")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ fun npeIfdsContext(
cp,
ifdsSystemOptions,
bannedPackagePrefixes,
chunkStrategy,
JcChunkResolver(chunkStrategy)
) { runnerId ->
val analyzer = when (runnerId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ fun taintIfdsContext(
cp,
ifdsSystemOptions,
bannedPackagePrefixes,
chunkStrategy,
JcChunkResolver(chunkStrategy)
) { runnerId ->
when (runnerId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ fun unusedIfdsContext(
cp,
ifdsSystemOptions,
bannedPackagePrefixes,
chunkStrategy,
JcChunkResolver(chunkStrategy)
) { runnerId ->
when (runnerId) {
Expand Down

0 comments on commit 1b5872c

Please sign in to comment.