Skip to content

Commit

Permalink
Wrong method reference for private method calls in Java 11 bytecode #140
Browse files Browse the repository at this point in the history
  • Loading branch information
lehvolk committed Jul 26, 2023
1 parent c73bd04 commit aa3ed10
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ abstract class MethodSignatureRef(
private val alwaysTrue: (JcTypedMethod) -> Boolean = { true }
}

private fun predicate(additionalFilter: (JcTypedMethod) -> Boolean = alwaysTrue): (JcTypedMethod) -> Boolean = {
it.name == name && additionalFilter(it) && it.method.description == description
}

protected val description: String = buildString {
append("(")
argTypes.forEach {
Expand All @@ -48,17 +52,16 @@ abstract class MethodSignatureRef(
}

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

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

protected fun JcClassType.findTypedMethodOrNull(filter: (JcTypedMethod) -> Boolean = alwaysTrue): JcTypedMethod? {
var methodOrNull = findMethodOrNull {
it.name == name && filter(it) && it.method.description == description
}
var methodOrNull = findMethodOrNull(predicate(filter))

if (methodOrNull == null && jcClass.packageName == "java.lang.invoke") {
methodOrNull = findMethodOrNull {
val method = it.method
Expand Down Expand Up @@ -194,11 +197,11 @@ class VirtualMethodRefImpl(
}

override val method: JcTypedMethod by softLazy {
actualType.findTypedMethodOrNull { !it.isPrivate } ?: declaredMethod
actualType.findTypedMethodOrNull() ?: declaredMethod
}

override val declaredMethod: JcTypedMethod by softLazy {
type.findTypedMethod { !it.isPrivate }
type.findTypedMethod()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ import org.jacodb.api.ext.cfg.callExpr
import org.jacodb.api.ext.cfg.locals
import org.jacodb.api.ext.cfg.values
import org.jacodb.testing.BaseTest
import org.jacodb.testing.Common
import org.jacodb.testing.WithDB
import org.jacodb.testing.cfg.RealMethodResolution.Virtual
import org.jacodb.testing.cfg.RealMethodResolution.VirtualImpl
import org.jacodb.testing.structure.FieldsAndMethods
import org.jacodb.testing.primitives.Primitives
import org.jacodb.testing.Common
import org.jacodb.testing.structure.FieldsAndMethods
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.DisabledOnJre
Expand Down Expand Up @@ -244,6 +244,15 @@ class InstructionsTest : BaseTest() {
assertEquals(cp.boolean, fieldBoolean.fieldType)
}

@Test
fun `private call with invokevirtual instruction`() {
val clazz = cp.findClass("VirtualInstructions")
val instList = clazz.declaredMethods.first { it.name == "run" }.instList
val callDoSmth = instList.mapNotNull { it.callExpr }. first {
it.toString().contains("doSmth")
}
assertEquals("doSmth", callDoSmth.method.method.name)
}
}

fun JcMethod.dumpInstructions(): String {
Expand Down
Binary file not shown.

0 comments on commit aa3ed10

Please sign in to comment.