Skip to content

Commit ee99492

Browse files
committed
Add cache for TaintConfigurationProvider
1 parent 81b6009 commit ee99492

File tree

7 files changed

+135
-30
lines changed

7 files changed

+135
-30
lines changed

gradle.properties

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ kryoSerializersVersion=0.45
6060
asmVersion=9.2
6161
testNgVersion=7.6.0
6262
mockitoInlineVersion=4.0.0
63-
kamlVersion = 0.51.0
64-
jacksonVersion = 2.12.3
63+
kamlVersion=0.51.0
64+
jacksonVersion=2.12.3
65+
kotlinxSerializationVersion=1.5.0
6566
slf4jVersion=1.7.36
6667
eclipseAetherVersion=1.1.0
6768
mavenWagonVersion=3.5.1

utbot-framework/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
plugins {
2+
id 'org.jetbrains.kotlin.plugin.serialization' version '1.7.20'
3+
}
4+
15
dependencies {
26

37
api project(':utbot-fuzzers')
@@ -19,6 +23,7 @@ dependencies {
1923

2024
implementation group: 'com.charleskorn.kaml', name: 'kaml', version: kamlVersion
2125
implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: jacksonVersion
26+
implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-serialization-cbor', version: kotlinxSerializationVersion
2227
implementation group: 'com.github.curious-odd-man', name: 'rgxgen', version: rgxgenVersion
2328
implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: log4j2Version
2429
implementation group: 'io.github.microutils', name: 'kotlin-logging', version: kotlinLoggingVersion

utbot-framework/src/main/kotlin/org/utbot/engine/UtBotSymbolicEngine.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,8 @@ class UtBotSymbolicEngine(
145145
private val taintMarkRegistry: TaintMarkRegistry = TaintMarkRegistry()
146146
private val taintMarkManager: TaintMarkManager = TaintMarkManager(taintMarkRegistry)
147147

148-
private val taintConfigProvider: TaintConfigurationProvider = TaintConfigurationProviderCombiner(listOf(
149-
TaintConfigurationProviderUserRules(taintUserConfigPath ?: ""),
150-
TaintConfigurationProviderResources("taint/config.yaml")
151-
))
152148
private val taintConfiguration: TaintConfiguration = if (UtSettings.useTaintAnalysis)
153-
taintConfigProvider.getConfiguration()
149+
constructDefaultProvider(taintUserConfigPath).getConfiguration()
154150
else
155151
TaintConfiguration() // empty
156152

utbot-framework/src/main/kotlin/org/utbot/taint/TaintConfigurationProvider.kt

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
11
package org.utbot.taint
22

3+
import kotlinx.serialization.ExperimentalSerializationApi
4+
import kotlinx.serialization.cbor.Cbor
5+
import kotlinx.serialization.decodeFromByteArray
6+
import kotlinx.serialization.encodeToByteArray
37
import org.utbot.common.PathUtil.toPath
8+
import org.utbot.common.utBotTempDirectory
49
import org.utbot.taint.model.TaintConfiguration
510
import org.utbot.taint.parser.TaintYamlParser
11+
import java.io.File
612

713
/**
814
* Provide the [TaintConfiguration].
915
*/
1016
interface TaintConfigurationProvider {
17+
18+
/**
19+
* Returns the time that the configuration was last modified.
20+
*
21+
* Uses the same format as the [java.io.File.lastModified].
22+
*/
23+
fun lastModified(): Long
24+
25+
/**
26+
* Provides [TaintConfiguration].
27+
*/
1128
fun getConfiguration(): TaintConfiguration
1229
}
1330

@@ -17,6 +34,12 @@ interface TaintConfigurationProvider {
1734
* @param configPath relative path to the .yaml file in resources
1835
*/
1936
class TaintConfigurationProviderResources(private val configPath: String) : TaintConfigurationProvider {
37+
38+
override fun lastModified(): Long {
39+
val selfJarFile = File(javaClass.protectionDomain.codeSource.location.toURI().path)
40+
return selfJarFile.lastModified()
41+
}
42+
2043
override fun getConfiguration(): TaintConfiguration {
2144
val configUrl = javaClass.classLoader.getResource(configPath)
2245
?: return TaintConfiguration()
@@ -32,6 +55,15 @@ class TaintConfigurationProviderResources(private val configPath: String) : Tain
3255
* @param configPath relative path to the .yaml file in the user's project.
3356
*/
3457
class TaintConfigurationProviderUserRules(private val configPath: String) : TaintConfigurationProvider {
58+
59+
override fun lastModified(): Long {
60+
val configFile = configPath.toPath().toFile()
61+
if (!configFile.exists()) {
62+
return 0
63+
}
64+
return configFile.lastModified()
65+
}
66+
3567
override fun getConfiguration(): TaintConfiguration {
3668
val configFile = configPath.toPath().toFile()
3769
if (!configFile.exists()) {
@@ -43,11 +75,64 @@ class TaintConfigurationProviderUserRules(private val configPath: String) : Tain
4375
}
4476
}
4577

78+
/**
79+
* Combines taint configurations from several providers.
80+
*/
4681
class TaintConfigurationProviderCombiner(private val inners: List<TaintConfigurationProvider>) : TaintConfigurationProvider {
82+
83+
override fun lastModified(): Long {
84+
return inners.maxOf { it.lastModified() }
85+
}
86+
4787
override fun getConfiguration(): TaintConfiguration =
4888
inners.fold(TaintConfiguration()) { resultConfig, configProvider ->
4989
resultConfig + configProvider.getConfiguration()
5090
}
5191
}
5292

53-
// TODO: TaintConfigurationProviderCached -- stores binary config to the temp directory
93+
/**
94+
* Stores binary configuration file to the utbot temp directory to reduce parsing time in the future.
95+
*
96+
* @param nameSuffix the cached file will have "-$nameSuffix" suffix
97+
* @param inner provider to cache
98+
*/
99+
class TaintConfigurationProviderCached(
100+
nameSuffix: String,
101+
private val inner: TaintConfigurationProvider,
102+
) : TaintConfigurationProvider {
103+
104+
private val cachedConfigName = "taint-config-cached-$nameSuffix"
105+
106+
private val cachedConfigFile = utBotTempDirectory.resolve(cachedConfigName).toFile()
107+
108+
override fun lastModified(): Long {
109+
return cachedConfigFile.lastModified()
110+
}
111+
112+
@OptIn(ExperimentalSerializationApi::class)
113+
override fun getConfiguration(): TaintConfiguration =
114+
if (!cachedConfigFile.exists() || cachedConfigFile.lastModified() < inner.lastModified()) {
115+
val config = inner.getConfiguration()
116+
val bytes = Cbor.encodeToByteArray(config)
117+
cachedConfigFile.writeBytes(bytes)
118+
config
119+
} else {
120+
val bytes = cachedConfigFile.readBytes()
121+
Cbor.decodeFromByteArray(bytes)
122+
}
123+
}
124+
125+
fun constructDefaultProvider(
126+
taintUserConfigPath: String?,
127+
taintResourcesConfigPath: String = "taint/config.yaml"
128+
): TaintConfigurationProvider {
129+
val resourcesConfig = TaintConfigurationProviderResources(taintResourcesConfigPath)
130+
val cachedResourcesConfig = TaintConfigurationProviderCached("resources", resourcesConfig)
131+
132+
val cachedUserConfigOrNull = taintUserConfigPath?.let {
133+
val userConfig = TaintConfigurationProviderUserRules(taintUserConfigPath)
134+
TaintConfigurationProviderCached("user", userConfig)
135+
}
136+
137+
return TaintConfigurationProviderCombiner(listOfNotNull(cachedUserConfigOrNull, cachedResourcesConfig))
138+
}
Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
11
package org.utbot.taint.model
22

3+
import kotlinx.serialization.Serializable
4+
35
// Data classes corresponding to the parsed data transfer objects.
46
// See [org.utbot.taint.parser.model] for more details.
57

8+
@Serializable
69
data class MethodFqn(
710
val packageNames: List<String>,
811
val className: String,
912
val methodName: String
1013
)
1114

15+
@Serializable
1216
sealed interface TaintEntities {
1317
val entities: Collection<TaintEntity>
1418
}
15-
data class TaintEntitiesSet(override val entities: Set<TaintEntity>) : TaintEntities
19+
@Serializable data class TaintEntitiesSet(override val entities: Set<TaintEntity>) : TaintEntities
1620

17-
sealed interface TaintMarks
18-
object TaintMarksAll : TaintMarks
19-
data class TaintMarksSet(val marks: Set<TaintMark>) : TaintMarks
21+
@Serializable sealed interface TaintMarks
22+
@Serializable object TaintMarksAll : TaintMarks
23+
@Serializable data class TaintMarksSet(val marks: Set<TaintMark>) : TaintMarks
2024

21-
sealed interface TaintEntity
22-
object TaintEntityThis : TaintEntity
23-
object TaintEntityReturn : TaintEntity
24-
data class TaintEntityArgument(/** one-based */ val index: UInt) : TaintEntity
25+
@Serializable sealed interface TaintEntity
26+
@Serializable object TaintEntityThis : TaintEntity
27+
@Serializable object TaintEntityReturn : TaintEntity
28+
@Serializable data class TaintEntityArgument(/** one-based */ val index: UInt) : TaintEntity
2529

26-
data class TaintMark(val name: String)
30+
@Serializable data class TaintMark(val name: String)
2731

28-
sealed interface ArgumentValue
29-
object ArgumentValueNull : ArgumentValue
30-
data class ArgumentValueBoolean(val value: Boolean) : ArgumentValue
31-
data class ArgumentValueLong(val value: Long) : ArgumentValue
32-
data class ArgumentValueDouble(val value: Double) : ArgumentValue
33-
data class ArgumentValueString(val value: String) : ArgumentValue
32+
@Serializable sealed interface ArgumentValue
33+
@Serializable object ArgumentValueNull : ArgumentValue
34+
@Serializable data class ArgumentValueBoolean(val value: Boolean) : ArgumentValue
35+
@Serializable data class ArgumentValueLong(val value: Long) : ArgumentValue
36+
@Serializable data class ArgumentValueDouble(val value: Double) : ArgumentValue
37+
@Serializable data class ArgumentValueString(val value: String) : ArgumentValue
3438

35-
sealed interface ArgumentType
36-
object ArgumentTypeAny : ArgumentType
37-
data class ArgumentTypeString(val typeFqn: String) : ArgumentType
39+
@Serializable sealed interface ArgumentType
40+
@Serializable object ArgumentTypeAny : ArgumentType
41+
@Serializable data class ArgumentTypeString(val typeFqn: String) : ArgumentType
3842

39-
sealed interface TaintSignature
40-
object TaintSignatureAny : TaintSignature
41-
data class TaintSignatureList(val argumentTypes: List<ArgumentType>) : TaintSignature
43+
@Serializable sealed interface TaintSignature
44+
@Serializable object TaintSignatureAny : TaintSignature
45+
@Serializable data class TaintSignatureList(val argumentTypes: List<ArgumentType>) : TaintSignature

utbot-framework/src/main/kotlin/org/utbot/taint/model/TaintCondition.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
package org.utbot.taint.model
22

3+
import kotlinx.serialization.Serializable
34
import org.utbot.engine.*
45
import org.utbot.engine.pc.*
56
import soot.Scene
67

78
/**
89
* Condition that imposed on the taint rule. It must be met to trigger the rule.
910
*/
10-
interface TaintCondition {
11+
@Serializable
12+
sealed interface TaintCondition {
1113
fun toBoolExpr(traverser: Traverser, methodData: SymbolicMethodData): UtBoolExpression
1214
}
1315

1416
/**
1517
* Returns always true.
1618
*/
19+
@Serializable
1720
object ConditionTrue : TaintCondition {
1821
override fun toBoolExpr(traverser: Traverser, methodData: SymbolicMethodData): UtBoolExpression =
1922
UtTrue
@@ -22,6 +25,7 @@ object ConditionTrue : TaintCondition {
2225
/**
2326
* The [entity] must be equal to [argumentValue].
2427
*/
28+
@Serializable
2529
class ConditionEqualValue(
2630
private val entity: TaintEntity,
2731
private val argumentValue: ArgumentValue
@@ -67,6 +71,7 @@ class ConditionEqualValue(
6771
/**
6872
* The [entity] must be [argumentType] at the runtime.
6973
*/
74+
@Serializable
7075
class ConditionIsType(
7176
private val entity: TaintEntity,
7277
private val argumentType: ArgumentType
@@ -100,6 +105,7 @@ class ConditionIsType(
100105
/**
101106
* Negates [inner].
102107
*/
108+
@Serializable
103109
class ConditionNot(private val inner: TaintCondition) : TaintCondition {
104110
override fun toBoolExpr(traverser: Traverser, methodData: SymbolicMethodData): UtBoolExpression =
105111
mkNot(inner.toBoolExpr(traverser, methodData))
@@ -108,6 +114,7 @@ class ConditionNot(private val inner: TaintCondition) : TaintCondition {
108114
/**
109115
* Combines [inners] with `or` operator.
110116
*/
117+
@Serializable
111118
class ConditionOr(private val inners: List<TaintCondition>) : TaintCondition {
112119
override fun toBoolExpr(traverser: Traverser, methodData: SymbolicMethodData): UtBoolExpression =
113120
mkOr(inners.map { it.toBoolExpr(traverser, methodData) })
@@ -116,6 +123,7 @@ class ConditionOr(private val inners: List<TaintCondition>) : TaintCondition {
116123
/**
117124
* Combines [inners] with `and` operator.
118125
*/
126+
@Serializable
119127
class ConditionAnd(private val inners: List<TaintCondition>) : TaintCondition {
120128
override fun toBoolExpr(traverser: Traverser, methodData: SymbolicMethodData): UtBoolExpression =
121129
mkAnd(inners.map { it.toBoolExpr(traverser, methodData) })

utbot-framework/src/main/kotlin/org/utbot/taint/model/TaintConfiguration.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.utbot.taint.model
22

3+
import kotlinx.serialization.Serializable
34
import org.utbot.framework.plugin.api.ClassId
45
import org.utbot.framework.plugin.api.ExecutableId
56

67
/**
78
* Storage for all taint rules.
89
*/
10+
@Serializable
911
data class TaintConfiguration(
1012
private val sources: List<TaintSource> = listOf(),
1113
private val passes: List<TaintPass> = listOf(),
@@ -77,6 +79,7 @@ data class TaintConfiguration(
7779
* @param signature list of argument types (at compile time)
7880
* @param condition condition that must be met to trigger this rule
7981
*/
82+
@Serializable
8083
data class TaintSource(
8184
val methodFqn: MethodFqn,
8285
val addTo: TaintEntities,
@@ -93,6 +96,7 @@ data class TaintSource(
9396
* @param signature list of argument types (at compile time)
9497
* @param condition condition that must be met to trigger this rule
9598
*/
99+
@Serializable
96100
data class TaintPass(
97101
val methodFqn: MethodFqn,
98102
val getFrom: TaintEntities,
@@ -109,6 +113,7 @@ data class TaintPass(
109113
* @param signature list of argument types (at compile time)
110114
* @param condition condition that must be met to trigger this rule
111115
*/
116+
@Serializable
112117
data class TaintCleaner(
113118
val methodFqn: MethodFqn,
114119
val removeFrom: TaintEntities,
@@ -125,6 +130,7 @@ data class TaintCleaner(
125130
* @param signature list of argument types (at compile time)
126131
* @param condition condition that must be met to trigger this rule
127132
*/
133+
@Serializable
128134
data class TaintSink(
129135
val methodFqn: MethodFqn,
130136
val check: TaintEntities,

0 commit comments

Comments
 (0)