fix: Classes not being written properly because of array shifting

We now use a MutableList to replace it at the proper index, and use a ListBackedSet, so we don't copy List's to Set's for no reason.
This was a very bad issue. The array was shifted every time we removed the original class, the fact we even got a "working" dex file surprises me. Thankfully, this issue is now solved, and we lived happily after.
This commit is contained in:
Lucaskyy 2022-04-09 23:41:54 +02:00
parent 433914feda
commit 147195647c
No known key found for this signature in database
GPG key ID: 1530BFF96D1EEB89
4 changed files with 21 additions and 12 deletions

View file

@ -1,11 +1,11 @@
package app.revanced.patcher
import app.revanced.patcher.cache.Cache
import app.revanced.patcher.extensions.replace
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.signature.resolver.SignatureResolver
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.util.ListBackedSet
import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.DexIO
import lanchon.multidexlib2.MultiDexIO
@ -33,7 +33,7 @@ class Patcher(
init {
val dexFile = MultiDexIO.readDexFile(true, input, NAMER, null, null)
opcodes = dexFile.opcodes
cache = Cache(dexFile.classes.toMutableSet(), SignatureResolver(dexFile.classes, signatures).resolve())
cache = Cache(dexFile.classes.toMutableList(), SignatureResolver(dexFile.classes, signatures).resolve())
}
/**
* Add additional dex file container to the patcher.
@ -62,13 +62,13 @@ class Patcher(
// this is a slow workaround for now
cache.methodMap.values.forEach {
if (it.definingClassProxy.proxyUsed) {
cache.classes.replace(it.definingClassProxy.originalIndex, it.definingClassProxy.mutatedClass)
cache.classes[it.definingClassProxy.originalIndex] = it.definingClassProxy.mutatedClass
}
}
cache.classProxy.filter { it.proxyUsed }.forEach { proxy ->
cache.classes.replace(proxy.originalIndex, proxy.mutatedClass)
cache.classes[proxy.originalIndex] = proxy.mutatedClass
}
return cache.classes
return ListBackedSet(cache.classes)
}
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: MutableSet<ClassDef>,
internal val classes: MutableList<ClassDef>,
val methodMap: MethodMap
) {
// TODO: currently we create ClassProxies at multiple places, which is why we could have merge conflicts

View file

@ -3,7 +3,6 @@ package app.revanced.patcher.extensions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.builder.BuilderInstruction
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.iface.ClassDef
infix fun AccessFlags.or(other: AccessFlags) = this.value or other.value
@ -12,8 +11,3 @@ fun MutableMethodImplementation.addInstructions(index: Int, instructions: List<B
this.addInstruction(index, instructions[i])
}
}
internal fun MutableSet<ClassDef>.replace(originalIndex: Int, mutatedClass: ClassDef) {
this.remove(this.elementAt(originalIndex))
this.add(mutatedClass)
}

View file

@ -0,0 +1,15 @@
package app.revanced.patcher.util
class ListBackedSet<E>(private val list: MutableList<E>) : MutableSet<E> {
override val size get() = list.size
override fun add(element: E) = list.add(element)
override fun addAll(elements: Collection<E>) = list.addAll(elements)
override fun clear() = list.clear()
override fun iterator() = list.listIterator()
override fun remove(element: E) = list.remove(element)
override fun removeAll(elements: Collection<E>) = list.removeAll(elements)
override fun retainAll(elements: Collection<E>) = list.retainAll(elements)
override fun contains(element: E) = list.contains(element)
override fun containsAll(elements: Collection<E>) = list.containsAll(elements)
override fun isEmpty() = list.isEmpty()
}