Skip to content

Commit

Permalink
Add ark taint test
Browse files Browse the repository at this point in the history
  • Loading branch information
rudolf101 committed Jun 18, 2024
1 parent d1e2b12 commit 6296ae0
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ import org.jacodb.api.common.analysis.ApplicationGraph
import org.jacodb.api.common.cfg.CommonCallExpr
import org.jacodb.api.common.cfg.CommonInst
import org.jacodb.api.jvm.cfg.JcInst
import org.jacodb.panda.dynamic.ark.base.Stmt
import java.util.concurrent.ConcurrentHashMap
import org.jacodb.api.jvm.ext.cfg.callExpr as jcCallExpr
import org.jacodb.panda.dynamic.api.PandaInst as DynamicPandaInst
import org.jacodb.panda.dynamic.api.callExpr as dynamicPandaCallExpr
import org.jacodb.panda.dynamic.ark.base.callExpr as arkCallExpr
import org.jacodb.panda.staticvm.cfg.PandaInst as StaticPandaInst
import org.jacodb.panda.staticvm.utils.callExpr as staticPandaCallExpr

Expand Down Expand Up @@ -65,6 +67,7 @@ class UniRunner<Fact, Event, Method, Statement>(
is JcInst -> jcCallExpr
is DynamicPandaInst -> dynamicPandaCallExpr
is StaticPandaInst -> staticPandaCallExpr
is Stmt -> arkCallExpr
else -> error("Unsupported statement type: $this")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import org.jacodb.panda.dynamic.ark.base.StaticFieldRef
import org.jacodb.panda.dynamic.ark.base.Stmt
import org.jacodb.panda.dynamic.ark.model.ArkFile
import org.jacodb.panda.dynamic.ark.model.ArkMethod
import org.jacodb.panda.dynamic.ark.model.ArkMethodImpl
import org.jacodb.panda.dynamic.ark.model.ArkMethodParameter
import org.jacodb.taint.configuration.ConstantValue
import org.jacodb.analysis.util.toPath as _toPath
Expand All @@ -51,7 +52,8 @@ interface ArkTraits : Traits<ArkMethod, Stmt> {
override val CommonCallExpr.callee: ArkMethod
get() {
check(this is CallExpr)
return cp.getMethodBySignature(method) ?: error("Method not found: $method")
// return cp.getMethodBySignature(method) ?: error("Method not found: $method")
return ArkMethodImpl(method, emptyList())
}

override val ArkMethod.thisInstance: ArkThis
Expand Down Expand Up @@ -106,7 +108,7 @@ interface ArkTraits : Traits<ArkMethod, Stmt> {
}

override fun Stmt.getCallExpr(): CallExpr? {
return _getOperands().filterIsInstance<CallExpr>().firstOrNull()
return callExpr
}

override fun CommonExpr.getValues(): Set<ArkValue> {
Expand Down Expand Up @@ -152,3 +154,6 @@ fun ArkEntity.toPathOrNull(): AccessPath? = when (this) {
fun ArkEntity.toPath(): AccessPath {
return toPathOrNull() ?: error("Unable to build access path for value $this")
}

val Stmt.callExpr: CallExpr?
get() = _getOperands().filterIsInstance<CallExpr>().firstOrNull()
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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.panda.dynamic.ark.base

import org.jacodb.panda.dynamic.ark.utils.getOperands

val Stmt.callExpr: CallExpr?
get() = getOperands().filterIsInstance<CallExpr>().firstOrNull()
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
package org.jacodb.panda.dynamic.ark.graph

import org.jacodb.api.common.analysis.ApplicationGraph
import org.jacodb.panda.dynamic.ark.base.CallExpr
import org.jacodb.panda.dynamic.ark.base.CallStmt
import org.jacodb.panda.dynamic.ark.base.Stmt
import org.jacodb.panda.dynamic.ark.model.ArkFile
import org.jacodb.panda.dynamic.ark.model.ArkMethod
import org.jacodb.panda.dynamic.ark.utils.getOperands

class ArkApplicationGraph(
override val project: ArkFile
Expand All @@ -39,7 +41,7 @@ class ArkApplicationGraph(
}

override fun callees(node: Stmt): Sequence<ArkMethod> {
val expr = (node as CallStmt).expr
val expr = node.getOperands().filterIsInstance<CallExpr>().firstOrNull() ?: return emptySequence()
val method = expr.method
val result = project.classes.asSequence().flatMap { it.methods }.filter { it.name == method.name }
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,17 @@ class ArkMethodImpl(
override fun toString(): String {
return signature.toString()
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as ArkMethodImpl

return signature == other.signature
}

override fun hashCode(): Int {
return signature.hashCode()
}
}
110 changes: 86 additions & 24 deletions jacodb-panda-dynamic/src/test/kotlin/ark/ArkTaintAnalysisTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,33 @@

package ark

import org.jacodb.analysis.ifds.SingletonUnit
import org.jacodb.analysis.ifds.UnitResolver
import org.jacodb.analysis.taint.ForwardTaintFlowFunctions
import org.jacodb.analysis.taint.TaintManager
import org.jacodb.analysis.util.ArkTraits
import org.jacodb.panda.dynamic.ark.base.Stmt
import org.jacodb.panda.dynamic.ark.dto.ArkFileDto
import org.jacodb.panda.dynamic.ark.dto.convertToArkFile
import org.jacodb.panda.dynamic.ark.graph.ArkApplicationGraph
import org.jacodb.panda.dynamic.ark.model.ArkFile
import org.jacodb.panda.dynamic.ark.model.ArkMethod
import org.jacodb.taint.configuration.Argument
import org.jacodb.taint.configuration.AssignMark
import org.jacodb.taint.configuration.ConstantTrue
import org.jacodb.taint.configuration.ContainsMark
import org.jacodb.taint.configuration.CopyAllMarks
import org.jacodb.taint.configuration.RemoveMark
import org.jacodb.taint.configuration.Result
import org.jacodb.taint.configuration.TaintConfigurationItem
import org.jacodb.taint.configuration.TaintMark
import org.jacodb.taint.configuration.TaintMethodSink
import org.jacodb.taint.configuration.TaintMethodSource
import org.jacodb.taint.configuration.TaintPassThrough
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import kotlin.time.Duration.Companion.seconds

private val logger = mu.KotlinLogging.logger {}

Expand All @@ -38,28 +61,67 @@ class ArkTaintAnalysisTest {
}
}

// @Test
// fun `test taint analysis`() {
// val arkFile = loadArkFile("taint")
// val graph = ArkApplicationGraph(arkFile)
// val unitResolver = UnitResolver<ArkMethod> { SingletonUnit }
// val getConfigForMethod: ForwardTaintFlowFunctions<ArkMethod, Stmt>.(ArkMethod) -> List<TaintConfigurationItem>? =
// { _ ->
// null
// }
// val manager = TaintManager(
// graph = graph,
// unitResolver = unitResolver,
// getConfigForMethod = getConfigForMethod,
// )
//
// val methods = project.classes.flatMap { it.methods }
// logger.info { "Methods: ${methods.size}" }
// for (method in methods) {
// logger.info { " ${method.name}" }
// }
// val sinks = manager.analyze(methods, timeout = 60.seconds)
// logger.info { "Sinks: $sinks" }
// assertTrue(sinks.isNotEmpty())
// }
@Disabled("Doesn't work yet")
@Test
fun `test taint analysis`() {
val arkFile = loadArkFile("taint")
ArkTraits.cp = arkFile
val graph = ArkApplicationGraph(arkFile)
val unitResolver = UnitResolver<ArkMethod> { SingletonUnit }
val getConfigForMethod: ForwardTaintFlowFunctions<ArkMethod, Stmt>.(ArkMethod) -> List<TaintConfigurationItem>? =
{ method ->
val rules = buildList {
if (method.name == "source") add(
TaintMethodSource(
method = method,
condition = ConstantTrue,
actionsAfter = listOf(
AssignMark(mark = TaintMark("TAINT"), position = Result),
),
)
)
if (method.name == "sink") add(
TaintMethodSink(
method = method,
ruleNote = "SINK", // FIXME
cwe = listOf(), // FIXME
condition = ContainsMark(position = Argument(0), mark = TaintMark("TAINT"))
)
)
if (method.name == "pass") add(
TaintPassThrough(
method = method,
condition = ConstantTrue,
actionsAfter = listOf(
CopyAllMarks(from = Argument(0), to = Result)
),
)
)
if (method.name == "validate") add(
TaintPassThrough(
method = method,
condition = ConstantTrue,
actionsAfter = listOf(
RemoveMark(mark = TaintMark("TAINT"), position = Argument(0))
),
)
)
}
rules.ifEmpty { null }
}
val manager = TaintManager(
graph = graph,
unitResolver = unitResolver,
getConfigForMethod = getConfigForMethod,
)

val methods = arkFile.classes.flatMap { it.methods }
logger.info { "Methods: ${methods.size}" }
for (method in methods) {
logger.info { " ${method.name}" }
}
val sinks = manager.analyze(methods, timeout = 60.seconds)
logger.info { "Sinks: $sinks" }
assertTrue(sinks.isNotEmpty())
}
}

0 comments on commit 6296ae0

Please sign in to comment.