|
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