fix: fix classes having multiple method instances

This commit is contained in:
oSumAtrIX 2022-04-05 03:52:00 +02:00
parent 05e44007d8
commit 12c10d8c64
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
6 changed files with 54 additions and 34 deletions

View file

@ -29,7 +29,7 @@ class Patcher(
init {
val dexFile = MultiDexIO.readDexFile(true, input, BasicDexFileNamer(), null, null)
cache = Cache(dexFile.classes, SignatureResolver(dexFile.classes, signatures).resolve())
cache = Cache(dexFile.classes.toMutableSet(), SignatureResolver(dexFile.classes, signatures).resolve())
}
/**
@ -39,13 +39,13 @@ class Patcher(
val newDexFile = object : DexFile {
override fun getClasses(): Set<ClassDef> {
// this is a slow workaround for now
val classes = cache.classes.toMutableSet()
cache.classProxy
.filter { it.proxyUsed }.forEach { proxy ->
classes.remove(classes.elementAt(proxy.originalIndex))
classes.add(proxy.mutatedClass)
cache.classes.remove(cache.classes.elementAt(proxy.originalIndex))
cache.classes.add(proxy.mutatedClass)
}
return classes
return setOf(cache.classProxy.first().mutatedClass)
}
override fun getOpcodes(): Opcodes {

View file

@ -5,7 +5,7 @@ import app.revanced.patcher.signature.SignatureResolverResult
import org.jf.dexlib2.iface.ClassDef
class Cache(
internal val classes: Set<ClassDef>,
internal val classes: MutableSet<ClassDef>,
val resolvedMethods: MethodMap
) {
// TODO: currently we create ClassProxies at multiple places, which is why we could have merge conflicts

View file

@ -3,8 +3,10 @@ package app.revanced.patcher.proxy.mutableTypes
import app.revanced.patcher.proxy.mutableTypes.MutableAnnotation.Companion.toMutable
import app.revanced.patcher.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.proxy.mutableTypes.MutableMethod.Companion.toMutable
import com.google.common.collect.Iterables
import org.jf.dexlib2.base.reference.BaseTypeReference
import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.util.MethodUtil
class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
// Class
@ -14,17 +16,23 @@ class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
private var superclass = classDef.superclass
private val _interfaces by lazy { classDef.interfaces.toMutableList() }
private val _annotations by lazy { classDef.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() }
private val _annotations by lazy {
classDef.annotations.map { annotation -> annotation.toMutable() }.toMutableSet()
}
// Methods
private val _methods by lazy { classDef.methods.map { method -> method.toMutable() }.toMutableSet() }
private val _directMethods by lazy { classDef.directMethods.map { directMethod -> directMethod.toMutable() }.toMutableSet() }
private val _virtualMethods by lazy { classDef.virtualMethods.map { virtualMethod -> virtualMethod.toMutable() }.toMutableSet() }
private val _directMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_DIRECT).toMutableSet() }
private val _virtualMethods by lazy { Iterables.filter(_methods, MethodUtil.METHOD_IS_VIRTUAL).toMutableSet() }
// Fields
private val _fields by lazy { classDef.fields.map { field -> field.toMutable() }.toMutableSet() }
private val _staticFields by lazy { classDef.staticFields.map { staticField -> staticField.toMutable() }.toMutableSet() }
private val _instanceFields by lazy { classDef.instanceFields.map { instanceFields -> instanceFields.toMutable() }.toMutableSet() }
private val _staticFields by lazy {
classDef.staticFields.map { staticField -> staticField.toMutable() }.toMutableSet()
}
private val _instanceFields by lazy {
classDef.instanceFields.map { instanceFields -> instanceFields.toMutable() }.toMutableSet()
}
fun setType(type: String) {
this.type = type

View file

@ -9,7 +9,9 @@ class MutableMethodParameter(parameter: MethodParameter) : MethodParameter, Base
private var type = parameter.type
private var name = parameter.name
private var signature = parameter.signature
private val _annotations by lazy { parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet() }
private val _annotations by lazy {
parameter.annotations.map { annotation -> annotation.toMutable() }.toMutableSet()
}
override fun getType(): String {
return type

View file

@ -5,7 +5,6 @@ import org.antlr.runtime.TokenSource
import org.antlr.runtime.tree.CommonTreeNodeStream
import org.jf.dexlib2.Opcodes
import org.jf.dexlib2.builder.BuilderInstruction
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.writer.builder.DexBuilder
import org.jf.smali.LexerErrorInterface
import org.jf.smali.smaliFlexLexer

View file

@ -11,6 +11,7 @@ import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.smali.asInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
@ -51,12 +52,12 @@ fun main() {
it.name.contains("HideReel")
}!!
val instructions = hideReelMethod.implementation!!
val implementation = hideReelMethod.implementation!!
val readInsn =
val readSettingsInstructionCompiled =
"invoke-static { }, Lfi/razerman/youtube/XGlobals;->ReadSettings()V"
.asInstruction() as BuilderInstruction35c
val testInsn = BuilderInstruction35c(
val readSettingsInstructionAssembled = BuilderInstruction35c(
Opcode.INVOKE_STATIC,
0, 0, 0, 0, 0, 0,
ImmutableMethodReference(
@ -67,30 +68,40 @@ fun main() {
)
)
assertEquals(testInsn.opcode, readInsn.opcode)
assertEquals(testInsn.referenceType, readInsn.referenceType)
assertEquals(testInsn.registerCount, readInsn.registerCount)
assertEquals(testInsn.registerC, readInsn.registerC)
assertEquals(testInsn.registerD, readInsn.registerD)
assertEquals(testInsn.registerE, readInsn.registerE)
assertEquals(testInsn.registerF, readInsn.registerF)
assertEquals(testInsn.registerG, readInsn.registerG)
assertEquals(readSettingsInstructionAssembled.opcode, readSettingsInstructionCompiled.opcode)
assertEquals(
readSettingsInstructionAssembled.referenceType,
readSettingsInstructionCompiled.referenceType
)
assertEquals(
readSettingsInstructionAssembled.registerCount,
readSettingsInstructionCompiled.registerCount
)
assertEquals(readSettingsInstructionAssembled.registerC, readSettingsInstructionCompiled.registerC)
assertEquals(readSettingsInstructionAssembled.registerD, readSettingsInstructionCompiled.registerD)
assertEquals(readSettingsInstructionAssembled.registerE, readSettingsInstructionCompiled.registerE)
assertEquals(readSettingsInstructionAssembled.registerF, readSettingsInstructionCompiled.registerF)
assertEquals(readSettingsInstructionAssembled.registerG, readSettingsInstructionCompiled.registerG)
run {
val tref = testInsn.reference as MethodReference
val rref = readInsn.reference as MethodReference
val compiledRef = readSettingsInstructionCompiled.reference as MethodReference
val assembledRef = readSettingsInstructionAssembled.reference as MethodReference
assertEquals(tref.name, rref.name)
assertEquals(tref.definingClass, rref.definingClass)
assertEquals(tref.returnType, rref.returnType)
assertContentEquals(tref.parameterTypes, rref.parameterTypes)
assertEquals(assembledRef.name, compiledRef.name)
assertEquals(assembledRef.definingClass, compiledRef.definingClass)
assertEquals(assembledRef.returnType, compiledRef.returnType)
assertContentEquals(assembledRef.parameterTypes, compiledRef.parameterTypes)
}
// TODO: figure out control flow
// otherwise the we would still jump over to the original instruction at index 21 instead to our new one
instructions.addInstruction(
implementation.addInstruction(
21,
readInsn
readSettingsInstructionCompiled
)
// fix labels
// create a new label for the instruction we want to jump to
val newLabel = implementation.newLabelForIndex(21)
// replace all instances of the old label with the new one
implementation.replaceInstruction(4, BuilderInstruction21t(Opcode.IF_NEZ, 0, newLabel))
return PatchResultSuccess()
}
},