Don't move static fields with to complex initializers

Depending on the class loading order, moving them can result in arrays
being empty, which breaks the client's functionality (e.g. it can't get
past the JS5 CRC check).
pull/66/head
Graham 4 years ago
parent 64ba68bac9
commit c70d810057
  1. 38
      deob/src/main/java/dev/openrs2/deob/transform/StaticScramblingTransformer.kt

@ -92,20 +92,24 @@ class StaticScramblingTransformer : Transformer() {
return entry.plus(exit) return entry.plus(exit)
} }
private fun MethodNode.extractInitializers(owner: String): Map<MemberDesc, InsnList> { private fun MethodNode.extractInitializers(owner: String): Pair<Map<MemberDesc, InsnList>, Set<MemberDesc>> {
val initializers = mutableMapOf<MemberDesc, InsnList>() val entryExitBlocks = extractEntryExitBlocks()
val putstatics = extractEntryExitBlocks() val simpleInitializers = mutableMapOf<MemberDesc, InsnList>()
val complexInitializers = instructions.asSequence()
.filter { !entryExitBlocks.contains(it) }
.filterIsInstance<FieldInsnNode>() .filterIsInstance<FieldInsnNode>()
.filter { it.opcode == Opcodes.PUTSTATIC } .filter { it.opcode == Opcodes.GETSTATIC && it.owner == owner && it.name !in TypedRemapper.EXCLUDED_FIELDS }
.map(::MemberDesc)
.toSet()
for (putstatic in putstatics) { val putstatics = entryExitBlocks
if (putstatic.owner != owner || putstatic.name in TypedRemapper.EXCLUDED_FIELDS) { .filterIsInstance<FieldInsnNode>()
continue .filter { it.opcode == Opcodes.PUTSTATIC && it.owner == owner && it.name !in TypedRemapper.EXCLUDED_FIELDS }
}
for (putstatic in putstatics) {
val desc = MemberDesc(putstatic) val desc = MemberDesc(putstatic)
if (initializers.containsKey(desc)) { if (simpleInitializers.containsKey(desc) || complexInitializers.contains(desc)) {
continue continue
} }
@ -120,10 +124,10 @@ class StaticScramblingTransformer : Transformer() {
instructions.remove(putstatic) instructions.remove(putstatic)
initializer.add(putstatic) initializer.add(putstatic)
initializers[desc] = initializer simpleInitializers[desc] = initializer
} }
return initializers return Pair(simpleInitializers, complexInitializers)
} }
private fun spliceInitializers() { private fun spliceInitializers() {
@ -139,7 +143,8 @@ class StaticScramblingTransformer : Transformer() {
} }
for (dependency in field.dependencies) { for (dependency in field.dependencies) {
spliceInitializers(done, dependency, fields[dependency]!!) val dependencyField = fields[dependency] ?: continue
spliceInitializers(done, dependency, dependencyField)
} }
val (clazz, clinit) = nextClass() val (clazz, clinit) = nextClass()
@ -171,7 +176,8 @@ class StaticScramblingTransformer : Transformer() {
} }
val clinit = clazz.methods.find { it.name == "<clinit>" } val clinit = clazz.methods.find { it.name == "<clinit>" }
val initializers = clinit?.extractInitializers(clazz.name) ?: emptyMap() val (simpleInitializers, complexInitializers) = clinit?.extractInitializers(clazz.name)
?: Pair(emptyMap(), emptySet())
clazz.fields.removeIf { field -> clazz.fields.removeIf { field ->
if (field.access and Opcodes.ACC_STATIC == 0) { if (field.access and Opcodes.ACC_STATIC == 0) {
@ -181,7 +187,11 @@ class StaticScramblingTransformer : Transformer() {
} }
val desc = MemberDesc(field) val desc = MemberDesc(field)
val initializer = initializers[desc] ?: InsnList() if (complexInitializers.contains(desc)) {
return@removeIf false
}
val initializer = simpleInitializers[desc] ?: InsnList()
val maxStack = clinit?.maxStack ?: 0 val maxStack = clinit?.maxStack ?: 0
val ref = MemberRef(clazz, field) val ref = MemberRef(clazz, field)

Loading…
Cancel
Save