Skip to content

Commit aa3ed10

Browse files
committed
Wrong method reference for private method calls in Java 11 bytecode #140
1 parent c73bd04 commit aa3ed10

3 files changed

Lines changed: 21 additions & 9 deletions

File tree

jacodb-core/src/main/kotlin/org/jacodb/impl/cfg/TypedMethodRefImpl.kt

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ abstract class MethodSignatureRef(
3838
private val alwaysTrue: (JcTypedMethod) -> Boolean = { true }
3939
}
4040

41+
private fun predicate(additionalFilter: (JcTypedMethod) -> Boolean = alwaysTrue): (JcTypedMethod) -> Boolean = {
42+
it.name == name && additionalFilter(it) && it.method.description == description
43+
}
44+
4145
protected val description: String = buildString {
4246
append("(")
4347
argTypes.forEach {
@@ -48,17 +52,16 @@ abstract class MethodSignatureRef(
4852
}
4953

5054
private fun List<JcTypedMethod>.findMethod(filter: (JcTypedMethod) -> Boolean = alwaysTrue): JcTypedMethod? {
51-
return firstOrNull { it.name == name && filter(it) && it.method.description == description }
55+
return firstOrNull(predicate(filter))
5256
}
5357

5458
protected fun JcClassType.findTypedMethod(filter: (JcTypedMethod) -> Boolean = alwaysTrue): JcTypedMethod {
55-
return findMethodOrNull(filter) ?: throw IllegalStateException(this.methodNotFoundMessage)
59+
return findMethodOrNull(predicate(filter)) ?: throw IllegalStateException(this.methodNotFoundMessage)
5660
}
5761

5862
protected fun JcClassType.findTypedMethodOrNull(filter: (JcTypedMethod) -> Boolean = alwaysTrue): JcTypedMethod? {
59-
var methodOrNull = findMethodOrNull {
60-
it.name == name && filter(it) && it.method.description == description
61-
}
63+
var methodOrNull = findMethodOrNull(predicate(filter))
64+
6265
if (methodOrNull == null && jcClass.packageName == "java.lang.invoke") {
6366
methodOrNull = findMethodOrNull {
6467
val method = it.method
@@ -194,11 +197,11 @@ class VirtualMethodRefImpl(
194197
}
195198

196199
override val method: JcTypedMethod by softLazy {
197-
actualType.findTypedMethodOrNull { !it.isPrivate } ?: declaredMethod
200+
actualType.findTypedMethodOrNull() ?: declaredMethod
198201
}
199202

200203
override val declaredMethod: JcTypedMethod by softLazy {
201-
type.findTypedMethod { !it.isPrivate }
204+
type.findTypedMethod()
202205
}
203206
}
204207

jacodb-core/src/test/kotlin/org/jacodb/testing/cfg/InstructionsTest.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ import org.jacodb.api.ext.cfg.callExpr
2929
import org.jacodb.api.ext.cfg.locals
3030
import org.jacodb.api.ext.cfg.values
3131
import org.jacodb.testing.BaseTest
32+
import org.jacodb.testing.Common
3233
import org.jacodb.testing.WithDB
3334
import org.jacodb.testing.cfg.RealMethodResolution.Virtual
3435
import org.jacodb.testing.cfg.RealMethodResolution.VirtualImpl
35-
import org.jacodb.testing.structure.FieldsAndMethods
3636
import org.jacodb.testing.primitives.Primitives
37-
import org.jacodb.testing.Common
37+
import org.jacodb.testing.structure.FieldsAndMethods
3838
import org.junit.jupiter.api.Assertions.*
3939
import org.junit.jupiter.api.Test
4040
import org.junit.jupiter.api.condition.DisabledOnJre
@@ -244,6 +244,15 @@ class InstructionsTest : BaseTest() {
244244
assertEquals(cp.boolean, fieldBoolean.fieldType)
245245
}
246246

247+
@Test
248+
fun `private call with invokevirtual instruction`() {
249+
val clazz = cp.findClass("VirtualInstructions")
250+
val instList = clazz.declaredMethods.first { it.name == "run" }.instList
251+
val callDoSmth = instList.mapNotNull { it.callExpr }. first {
252+
it.toString().contains("doSmth")
253+
}
254+
assertEquals("doSmth", callDoSmth.method.method.name)
255+
}
247256
}
248257

249258
fun JcMethod.dumpInstructions(): String {
688 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)