mirror of
https://github.com/revanced/revanced-patcher
synced 2024-11-24 05:16:22 +01:00
feat: add fuzzy resolver
fixed docs for MethodSignature & added tests for fuzzy resolver
This commit is contained in:
parent
18853f70a4
commit
7a56dca004
@ -46,20 +46,23 @@ data class MethodMetadata(
|
||||
|
||||
/**
|
||||
* Metadata for the Patcher, this contains things like how the Patcher should interpret this signature.
|
||||
* @param method The method the Patcher should use to resolve the signature.
|
||||
* @param method The method the resolver should use to resolve the signature.
|
||||
*/
|
||||
data class PatcherMetadata(
|
||||
val method: PatcherMethod
|
||||
val method: ResolverMethod
|
||||
)
|
||||
|
||||
interface PatcherMethod {
|
||||
/**
|
||||
* The method the resolver should use to resolve the signature.
|
||||
*/
|
||||
interface ResolverMethod {
|
||||
/**
|
||||
* When comparing the signature, if one or more of the opcodes do not match, skip.
|
||||
*/
|
||||
class Direct : PatcherMethod
|
||||
class Direct : ResolverMethod
|
||||
|
||||
/**
|
||||
* When comparing the signature, if [threshold] or more of the opcodes do not match, skip.
|
||||
*/
|
||||
class Fuzzy(val threshold: Int) : PatcherMethod
|
||||
class Fuzzy(val threshold: Int) : ResolverMethod
|
||||
}
|
@ -3,9 +3,9 @@ package app.revanced.patcher.signature.resolver
|
||||
import app.revanced.patcher.cache.MethodMap
|
||||
import app.revanced.patcher.proxy.ClassProxy
|
||||
import app.revanced.patcher.signature.MethodSignature
|
||||
import app.revanced.patcher.signature.ResolverMethod
|
||||
import app.revanced.patcher.signature.PatternScanResult
|
||||
import app.revanced.patcher.signature.SignatureResolverResult
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.ClassDef
|
||||
import org.jf.dexlib2.iface.Method
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
@ -75,10 +75,44 @@ internal class SignatureResolver(
|
||||
return if (signature.opcodes == null) {
|
||||
PatternScanResult(0, 0)
|
||||
} else {
|
||||
method.implementation?.instructions?.scanFor(signature.opcodes)
|
||||
method.implementation?.instructions?.let {
|
||||
compareOpcodes(signature, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun compareOpcodes(
|
||||
signature: MethodSignature,
|
||||
instructions: Iterable<Instruction>
|
||||
): PatternScanResult? {
|
||||
val count = instructions.count()
|
||||
val pattern = signature.opcodes!!
|
||||
val size = pattern.count()
|
||||
var threshold = 0
|
||||
if (signature.metadata.patcher.method is ResolverMethod.Fuzzy) {
|
||||
threshold = signature.metadata.patcher.method.threshold
|
||||
}
|
||||
|
||||
for (instructionIndex in 0 until count) {
|
||||
var patternIndex = 0
|
||||
var currentThreshold = threshold
|
||||
while (instructionIndex + patternIndex < count) {
|
||||
println("currentThreshold = $currentThreshold")
|
||||
if (
|
||||
instructions.elementAt(
|
||||
instructionIndex + patternIndex
|
||||
).opcode != pattern.elementAt(patternIndex)
|
||||
&& currentThreshold-- == 0
|
||||
) break
|
||||
if (++patternIndex < size) continue
|
||||
|
||||
return PatternScanResult(instructionIndex, instructionIndex + patternIndex)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun compareParameterTypes(
|
||||
signature: Iterable<String>,
|
||||
original: MutableList<out CharSequence>
|
||||
@ -89,20 +123,4 @@ internal class SignatureResolver(
|
||||
}
|
||||
|
||||
private operator fun ClassDef.component1() = this
|
||||
private operator fun ClassDef.component2() = this.methods
|
||||
|
||||
private fun MutableIterable<Instruction>.scanFor(pattern: Iterable<Opcode>): PatternScanResult? {
|
||||
val count = this.count()
|
||||
val size = pattern.count()
|
||||
for (instructionIndex in 0 until count) {
|
||||
var patternIndex = 0
|
||||
while (instructionIndex + patternIndex < count) {
|
||||
if (this.elementAt(instructionIndex + patternIndex).opcode != pattern.elementAt(patternIndex)) break
|
||||
if (++patternIndex < size) continue
|
||||
|
||||
return PatternScanResult(instructionIndex, instructionIndex + patternIndex)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
private operator fun ClassDef.component2() = this.methods
|
@ -38,7 +38,7 @@ internal class PatcherTest {
|
||||
comment = "Main method of TestClass. Version 1.0.0"
|
||||
),
|
||||
patcher = PatcherMetadata(
|
||||
method = PatcherMethod.Fuzzy(2)
|
||||
method = ResolverMethod.Fuzzy(2)
|
||||
)
|
||||
),
|
||||
"V",
|
||||
@ -46,7 +46,7 @@ internal class PatcherTest {
|
||||
listOf("[L"),
|
||||
listOf(
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.INVOKE_STATIC, // This is intentionally wrong to test the Fuzzy resolver.
|
||||
Opcode.RETURN_VOID
|
||||
)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user