fix: insert new filled array insn before first usage (#2340)
This commit is contained in:
@@ -25,7 +25,6 @@ import jadx.core.dex.nodes.IFieldInfoRef;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
|
||||
import jadx.core.utils.BlockUtils;
|
||||
import jadx.core.utils.InsnList;
|
||||
import jadx.core.utils.InsnRemover;
|
||||
import jadx.core.utils.InsnUtils;
|
||||
@@ -109,11 +108,15 @@ public class ReplaceNewArray extends AbstractVisitor {
|
||||
}
|
||||
// collect put instructions sorted by array index
|
||||
SortedMap<Long, InsnNode> arrPuts = new TreeMap<>();
|
||||
InsnNode firstNotAPutUsage = null;
|
||||
for (RegisterArg registerArg : useList) {
|
||||
InsnNode parentInsn = registerArg.getParentInsn();
|
||||
if (parentInsn == null
|
||||
|| parentInsn.getType() != InsnType.APUT
|
||||
|| !arrArg.sameRegAndSVar(parentInsn.getArg(0))) {
|
||||
if (firstNotAPutUsage == null) {
|
||||
firstNotAPutUsage = parentInsn;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Object constVal = InsnUtils.getConstValueByArg(mth.root(), parentInsn.getArg(1));
|
||||
@@ -158,12 +161,23 @@ public class ReplaceNewArray extends AbstractVisitor {
|
||||
remover.addAndUnbind(put);
|
||||
prevIndex = index;
|
||||
}
|
||||
// add missing trailing zeros
|
||||
for (long i = prevIndex + 1; i < len; i++) {
|
||||
filledArr.addArg(InsnArg.lit(0, elemType));
|
||||
}
|
||||
remover.addAndUnbind(newArrayInsn);
|
||||
|
||||
// place new insn at last array put or before first usage
|
||||
InsnNode lastPut = arrPuts.get(arrPuts.lastKey());
|
||||
int replaceIndex = InsnList.getIndex(instructions, lastPut);
|
||||
instructions.set(replaceIndex, filledArr);
|
||||
BlockUtils.replaceInsn(mth, lastPut, filledArr);
|
||||
int newInsnPos = InsnList.getIndex(instructions, lastPut);
|
||||
if (firstNotAPutUsage != null) {
|
||||
int idx = InsnList.getIndex(instructions, firstNotAPutUsage);
|
||||
if (idx != -1) {
|
||||
// TODO: check that all args already assigned
|
||||
newInsnPos = Math.min(idx, newInsnPos);
|
||||
}
|
||||
}
|
||||
instructions.add(newInsnPos, filledArr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package jadx.tests.integration.arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestArrayInitField2 extends SmaliTest {
|
||||
@Test
|
||||
public void test() {
|
||||
forceDecompiledCheck();
|
||||
assertThat(getClassNodeFromSmali())
|
||||
.code()
|
||||
.containsOne("static long[] myArr = {1282979400, 0, 0};");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
.class public Larrays/TestArrayInitField2;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.field static myArr:[J
|
||||
|
||||
.method static constructor <clinit>()V
|
||||
.locals 4
|
||||
|
||||
const v0, 0x3
|
||||
new-array v0, v0, [J
|
||||
sput-object v0, Larrays/TestArrayInitField2;->myArr:[J
|
||||
const/4 v1, 0x0
|
||||
const-wide/32 v2, 0x4c78b648
|
||||
aput-wide v2, v0, v1
|
||||
return-void
|
||||
nop
|
||||
|
||||
.end method
|
||||
|
||||
.method public check()V
|
||||
.registers 5
|
||||
sget-object v0, Larrays/TestArrayInitField2;->myArr:[J
|
||||
invoke-static {v0}, Lorg/assertj/core/api/Assertions;->assertThat([J)Lorg/assertj/core/api/AbstractLongArrayAssert;
|
||||
move-result-object v0
|
||||
const/4 v1, 0x3
|
||||
invoke-virtual {v0, v1}, Lorg/assertj/core/api/AbstractLongArrayAssert;->hasSize(I)Lorg/assertj/core/api/AbstractLongArrayAssert;
|
||||
|
||||
sget-object v0, Larrays/TestArrayInitField2;->myArr:[J
|
||||
const/4 v1, 0x0
|
||||
aget-wide v0, v0, v1
|
||||
invoke-static {v0, v1}, Lorg/assertj/core/api/Assertions;->assertThat(J)Lorg/assertj/core/api/AbstractLongAssert;
|
||||
move-result-object v0
|
||||
const-wide/32 v2, 0x4c78b648
|
||||
invoke-virtual {v0, v2, v3}, Lorg/assertj/core/api/AbstractLongAssert;->isEqualTo(J)Lorg/assertj/core/api/AbstractLongAssert;
|
||||
return-void
|
||||
.end method
|
||||
Reference in New Issue
Block a user