Skip to content

Commit

Permalink
fix: Classes not being written properly because of array shifting
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Sculas committed Apr 9, 2022
1 parent 433914f commit 1471956
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 12 deletions.
10 changes: 5 additions & 5 deletions src/main/kotlin/app/revanced/patcher/Patcher.kt
@@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/app/revanced/patcher/cache/Cache.kt
Expand Up @@ -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
Expand Down
6 changes: 0 additions & 6 deletions src/main/kotlin/app/revanced/patcher/extensions/Extensions.kt
Expand Up @@ -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

Expand All @@ -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)
}
15 changes: 15 additions & 0 deletions src/main/kotlin/app/revanced/patcher/util/ListBackedSet.kt
@@ -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()
}

0 comments on commit 1471956

Please sign in to comment.