fix: reaching all constructors not possible

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
oSumAtrIX 2022-04-27 03:13:45 +02:00
parent ac36d19693
commit 37fa9949ec
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
4 changed files with 46 additions and 22 deletions

View file

@ -5,8 +5,10 @@ import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.builder.BuilderInstruction import org.jf.dexlib2.builder.BuilderInstruction
import org.jf.dexlib2.builder.MutableMethodImplementation import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.immutable.ImmutableMethod import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodImplementation import org.jf.dexlib2.immutable.ImmutableMethodImplementation
import org.jf.dexlib2.util.MethodUtil
infix fun AccessFlags.or(other: AccessFlags) = this.value or other.value infix fun AccessFlags.or(other: AccessFlags) = this.value or other.value
infix fun Int.or(other: AccessFlags) = this or other.value infix fun Int.or(other: AccessFlags) = this or other.value
@ -23,7 +25,7 @@ fun MutableMethodImplementation.addInstructions(index: Int, instructions: List<B
* This may be a positive or negative number. * This may be a positive or negative number.
* @return The **immutable** cloned method. Call [toMutable] or [cloneMutable] to get a **mutable** copy. * @return The **immutable** cloned method. Call [toMutable] or [cloneMutable] to get a **mutable** copy.
*/ */
fun Method.clone( internal fun Method.clone(
registerCount: Int = 0, registerCount: Int = 0,
): ImmutableMethod { ): ImmutableMethod {
val clonedImplementation = implementation?.let { val clonedImplementation = implementation?.let {
@ -52,6 +54,28 @@ fun Method.clone(
* This may be a positive or negative number. * This may be a positive or negative number.
* @return The **mutable** cloned method. Call [clone] to get an **immutable** copy. * @return The **mutable** cloned method. Call [clone] to get an **immutable** copy.
*/ */
fun Method.cloneMutable( internal fun Method.cloneMutable(
registerCount: Int = 0, registerCount: Int = 0,
) = clone(registerCount).toMutable() ) = clone(registerCount).toMutable()
internal fun Method.softCompareTo(
otherMethod: MethodReference
): Boolean {
if (MethodUtil.isConstructor(this) && !parametersEqual(this.parameterTypes, otherMethod.parameterTypes))
return false
return this.name == otherMethod.name
}
// FIXME: also check the order of parameters as different order equals different method overload
internal fun parametersEqual(
parameters1: Iterable<CharSequence>,
parameters2: Iterable<CharSequence>
): Boolean {
return parameters1.count() == parameters2.count() && parameters1.all { parameter ->
parameters2.any {
it.startsWith(
parameter
)
}
}
}

View file

@ -2,6 +2,7 @@ package app.revanced.patcher.methodWalker
import app.revanced.patcher.MethodNotFoundException import app.revanced.patcher.MethodNotFoundException
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.softCompareTo
import app.revanced.patcher.proxy.mutableTypes.MutableMethod import app.revanced.patcher.proxy.mutableTypes.MutableMethod
import org.jf.dexlib2.Format import org.jf.dexlib2.Format
import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
@ -38,13 +39,17 @@ class MethodWalker internal constructor(
Preconditions.checkFormat(instruction.opcode, Format.Format35c) Preconditions.checkFormat(instruction.opcode, Format.Format35c)
val newMethodRef = (instruction as Instruction35c).reference as MethodReference val newMethod = (instruction as Instruction35c).reference as MethodReference
val proxy = patcherData.findClass(newMethodRef.definingClass)!! val proxy = patcherData.findClass(newMethod.definingClass)!!
val methods = if (walkMutable) proxy.resolve().methods else proxy.immutableClass.methods val methods = if (walkMutable) proxy.resolve().methods else proxy.immutableClass.methods
currentMethod = methods.first { it.name == newMethodRef.name } currentMethod = methods.first { it ->
return@first it.softCompareTo(newMethod)
}
return this return this
} }
throw MethodNotFoundException("This method can not be walked at offset $offset inside the method ${currentMethod.name}") throw MethodNotFoundException("This method can not be walked at offset $offset inside the method ${currentMethod.name}")
} }
} }

View file

@ -1,5 +1,6 @@
package app.revanced.patcher.signature package app.revanced.patcher.signature
import app.revanced.patcher.extensions.softCompareTo
import app.revanced.patcher.proxy.ClassProxy import app.revanced.patcher.proxy.ClassProxy
import app.revanced.patcher.signature.resolver.SignatureResolver import app.revanced.patcher.signature.resolver.SignatureResolver
import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
@ -7,33 +8,33 @@ import org.jf.dexlib2.iface.Method
/** /**
* Represents the result of a [SignatureResolver]. * Represents the result of a [SignatureResolver].
* @param definingClassProxy The [ClassProxy] that the matching method was found in. * @param definingClassProxy The [ClassProxy] that the matching method was found in.
* @param resolvedMethodName The name of the actual matching method. * @param resolvedMethod The actual matching method.
* @param scanData Opcodes pattern scan result. * @param scanData Opcodes pattern scan result.
*/ */
data class SignatureResolverResult( data class SignatureResolverResult(
val definingClassProxy: ClassProxy, val definingClassProxy: ClassProxy,
val scanData: PatternScanResult, val scanData: PatternScanResult,
private val resolvedMethodName: String, private val resolvedMethod: Method,
) { ) {
/** /**
* Returns the **mutable** method by the [resolvedMethodName] from the [definingClassProxy]. * Returns the **mutable** method by the [resolvedMethod] from the [definingClassProxy].
* *
* Please note, this method allocates a [ClassProxy]. * Please note, this method allocates a [ClassProxy].
* Use [immutableMethod] where possible. * Use [immutableMethod] where possible.
*/ */
val method val method
get() = definingClassProxy.resolve().methods.first { get() = definingClassProxy.resolve().methods.first {
it.name == resolvedMethodName it.softCompareTo(resolvedMethod)
} }
/** /**
* Returns the **immutable** method by the [resolvedMethodName] from the [definingClassProxy]. * Returns the **immutable** method by the [resolvedMethod] from the [definingClassProxy].
* *
* If you need to modify the method, use [method] instead. * If you need to modify the method, use [method] instead.
*/ */
val immutableMethod: Method val immutableMethod: Method
get() = definingClassProxy.immutableClass.methods.first { get() = definingClassProxy.immutableClass.methods.first {
it.name == resolvedMethodName it.softCompareTo(resolvedMethod)
} }
fun findParentMethod(signature: MethodSignature): SignatureResolverResult? { fun findParentMethod(signature: MethodSignature): SignatureResolverResult? {

View file

@ -1,6 +1,7 @@
package app.revanced.patcher.signature.resolver package app.revanced.patcher.signature.resolver
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.parametersEqual
import app.revanced.patcher.proxy import app.revanced.patcher.proxy
import app.revanced.patcher.proxy.ClassProxy import app.revanced.patcher.proxy.ClassProxy
import app.revanced.patcher.signature.MethodSignature import app.revanced.patcher.signature.MethodSignature
@ -29,7 +30,7 @@ internal class SignatureResolver(
signature.result = SignatureResolverResult( signature.result = SignatureResolverResult(
classProxy, classProxy,
patternScanData, patternScanData,
method.name, method,
) )
} }
} }
@ -44,7 +45,7 @@ internal class SignatureResolver(
return SignatureResolverResult( return SignatureResolverResult(
classProxy, classProxy,
result, result,
method.name, method,
) )
} }
return null return null
@ -67,7 +68,7 @@ internal class SignatureResolver(
} }
signature.methodParameters?.let { signature.methodParameters?.let {
if (compareParameterTypes(signature.methodParameters, method.parameterTypes)) { if (!parametersEqual(signature.methodParameters, method.parameterTypes)) {
return null return null
} }
} }
@ -137,13 +138,6 @@ internal class SignatureResolver(
return null return null
} }
private fun compareParameterTypes(
signature: Iterable<String>,
original: MutableList<out CharSequence>
): Boolean {
return signature.count() != original.size || !(signature.all { a -> original.any { it.startsWith(a) } })
}
private fun generateWarnings( private fun generateWarnings(
signature: MethodSignature, signature: MethodSignature,
instructions: Iterable<Instruction>, instructions: Iterable<Instruction>,