|
16 | 16 |
|
17 | 17 | package org.jacodb.taint.configuration |
18 | 18 |
|
19 | | -import kotlinx.coroutines.runBlocking |
20 | 19 | import kotlinx.serialization.decodeFromString |
21 | 20 | import kotlinx.serialization.json.Json |
22 | 21 | import kotlinx.serialization.modules.SerializersModule |
23 | 22 | import kotlinx.serialization.modules.polymorphic |
24 | 23 | import kotlinx.serialization.modules.subclass |
25 | 24 | import org.jacodb.api.* |
26 | 25 | import org.jacodb.api.ext.* |
27 | | -import org.jacodb.impl.features.hierarchyExt |
28 | 26 | import java.nio.file.Path |
29 | 27 | import kotlin.io.path.readText |
30 | 28 |
|
@@ -295,31 +293,49 @@ class TaintConfigurationFeature private constructor( |
295 | 293 | return mkOr(types.flatMap { type -> position.map { TypeMatches(it, type) } }) |
296 | 294 | } |
297 | 295 |
|
298 | | - typeMatcher as ClassMatcher |
| 296 | + val typeMatchers = (typeMatcher as ClassMatcher).extractAlternatives() |
| 297 | + val unresolvedMatchers = mutableListOf<ClassMatcher>() |
| 298 | + val disjuncts = mutableListOf<Condition>() |
299 | 299 |
|
300 | | - val pkgMatcher = typeMatcher.pkg |
301 | | - val clsMatcher = typeMatcher.classNameMatcher |
302 | 300 | val cp = method.enclosingClass.classpath |
303 | 301 |
|
304 | | - if (pkgMatcher is NameExactMatcher && clsMatcher is NameExactMatcher) { |
| 302 | + for (matcher in typeMatchers) { |
| 303 | + val pkgMatcher = matcher.pkg |
| 304 | + val clsMatcher = matcher.classNameMatcher |
| 305 | + |
| 306 | + if (pkgMatcher !is NameExactMatcher || clsMatcher !is NameExactMatcher) { |
| 307 | + unresolvedMatchers += matcher |
| 308 | + continue |
| 309 | + } |
| 310 | + |
305 | 311 | val type = cp.findTypeOrNull("${pkgMatcher.name}$DOT_DELIMITER${clsMatcher.name}") |
306 | | - ?: return mkOr(emptyList()) |
307 | | - return mkOr(position.map { TypeMatches(it, type) }) |
308 | | - } |
| 312 | + ?: continue |
309 | 313 |
|
310 | | - val alternatives = typeMatcher.extractAlternatives() |
311 | | - val disjuncts = mutableListOf<Condition>() |
| 314 | + position.mapTo(disjuncts) { TypeMatches(it, type) } |
| 315 | + } |
312 | 316 |
|
313 | | - alternatives.forEach { classMatcher -> |
314 | | - val allClasses = runBlocking { |
315 | | - cp.hierarchyExt().findSubClasses(cp.objectClass, allHierarchy = true, includeOwn = true) |
| 317 | + if (unresolvedMatchers.isNotEmpty()) { |
| 318 | + val allClassNames = cp.registeredLocations.flatMapTo(hashSetOf()) { |
| 319 | + val names = it.jcLocation?.classNames ?: return@flatMapTo emptyList() |
| 320 | + names.map { name -> |
| 321 | + val packageName = name.substringBeforeLast(DOT_DELIMITER, missingDelimiterValue = "") |
| 322 | + val simpleName = name.substringAfterLast(DOT_DELIMITER) |
| 323 | + packageName to simpleName |
| 324 | + } |
316 | 325 | } |
317 | 326 |
|
318 | | - val types = allClasses.filter { |
319 | | - matches(classMatcher.pkg, it.packageName) && matches(classMatcher.classNameMatcher, it.simpleName) |
320 | | - } |
| 327 | + unresolvedMatchers.forEach { classMatcher -> |
| 328 | + val matchedClassNames = allClassNames.filter { (packageName, simpleName) -> |
| 329 | + matches(classMatcher.pkg, packageName) && matches(classMatcher.classNameMatcher, simpleName) |
| 330 | + } |
321 | 331 |
|
322 | | - disjuncts += types.flatMap { type -> position.map { TypeMatches(it, type.toType()) } }.toList() |
| 332 | + matchedClassNames.flatMapTo(disjuncts) { (packageName, simpleName) -> |
| 333 | + val type = cp.findTypeOrNull("${packageName}$DOT_DELIMITER${simpleName}") |
| 334 | + ?: return@flatMapTo emptyList() |
| 335 | + |
| 336 | + position.map { TypeMatches(it, type) } |
| 337 | + } |
| 338 | + } |
323 | 339 | } |
324 | 340 |
|
325 | 341 | return mkOr(disjuncts) |
|
0 commit comments