Commit 883429fa authored by Skylot's avatar Skylot

core: fix enum class processing for obfuscated code

parent 380ee75d
...@@ -28,6 +28,7 @@ import java.util.List; ...@@ -28,6 +28,7 @@ import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
// TODO: run after code shrinker at final stage
public class EnumVisitor extends AbstractVisitor { public class EnumVisitor extends AbstractVisitor {
private static final Logger LOG = LoggerFactory.getLogger(EnumVisitor.class); private static final Logger LOG = LoggerFactory.getLogger(EnumVisitor.class);
...@@ -91,6 +92,7 @@ public class EnumVisitor extends AbstractVisitor { ...@@ -91,6 +92,7 @@ public class EnumVisitor extends AbstractVisitor {
// move enum specific instruction from static method to separate list // move enum specific instruction from static method to separate list
BlockNode staticBlock = staticMethod.getBasicBlocks().get(0); BlockNode staticBlock = staticMethod.getBasicBlocks().get(0);
ClassInfo classInfo = cls.getClassInfo();
List<InsnNode> insns = new ArrayList<InsnNode>(); List<InsnNode> insns = new ArrayList<InsnNode>();
List<InsnNode> list = staticBlock.getInstructions(); List<InsnNode> list = staticBlock.getInstructions();
int size = list.size(); int size = list.size();
...@@ -100,13 +102,19 @@ public class EnumVisitor extends AbstractVisitor { ...@@ -100,13 +102,19 @@ public class EnumVisitor extends AbstractVisitor {
if (insn.getType() == InsnType.SPUT) { if (insn.getType() == InsnType.SPUT) {
IndexInsnNode fp = (IndexInsnNode) insn; IndexInsnNode fp = (IndexInsnNode) insn;
FieldInfo f = (FieldInfo) fp.getIndex(); FieldInfo f = (FieldInfo) fp.getIndex();
if (f.getName().equals("$VALUES")) { if (f.getDeclClass().equals(classInfo)) {
if (i == size - 1) { FieldNode fieldNode = cls.searchField(f);
cls.getMethods().remove(staticMethod); if (fieldNode != null
} else { && fieldNode.getAccessFlags().isSynthetic()
list.subList(0, i + 1).clear(); && fieldNode.getType().isArray()
&& fieldNode.getType().getArrayRootElement().equals(classInfo.getType())) {
if (i == size - 1) {
cls.getMethods().remove(staticMethod);
} else {
list.subList(0, i + 1).clear();
}
break;
} }
break;
} }
} }
} }
...@@ -122,7 +130,7 @@ public class EnumVisitor extends AbstractVisitor { ...@@ -122,7 +130,7 @@ public class EnumVisitor extends AbstractVisitor {
if (constrCls == null) { if (constrCls == null) {
continue; continue;
} }
if (!clsInfo.equals(cls.getClassInfo()) && !constrCls.getAccessFlags().isEnum()) { if (!clsInfo.equals(classInfo) && !constrCls.getAccessFlags().isEnum()) {
continue; continue;
} }
RegisterArg nameArg = (RegisterArg) insn.getArg(0); RegisterArg nameArg = (RegisterArg) insn.getArg(0);
...@@ -135,11 +143,11 @@ public class EnumVisitor extends AbstractVisitor { ...@@ -135,11 +143,11 @@ public class EnumVisitor extends AbstractVisitor {
EnumField field = new EnumField(name, insn.getArgsCount() - 2); EnumField field = new EnumField(name, insn.getArgsCount() - 2);
attr.getFields().add(field); attr.getFields().add(field);
for (int i = 2; i < insn.getArgsCount(); i++) { for (int i = 2; i < insn.getArgsCount(); i++) {
InsnArg constrArg;
InsnArg iArg = insn.getArg(i); InsnArg iArg = insn.getArg(i);
InsnArg constrArg = iArg;
if (iArg.isLiteral()) { if (iArg.isLiteral()) {
constrArg = iArg; constrArg = iArg;
} else { } else if (iArg.isRegister()) {
constrArg = CodeShrinker.inlineArgument(staticMethod, (RegisterArg) iArg); constrArg = CodeShrinker.inlineArgument(staticMethod, (RegisterArg) iArg);
if (constrArg == null) { if (constrArg == null) {
throw new JadxException("Can't inline constructor arg in enum: " + cls); throw new JadxException("Can't inline constructor arg in enum: " + cls);
...@@ -148,7 +156,7 @@ public class EnumVisitor extends AbstractVisitor { ...@@ -148,7 +156,7 @@ public class EnumVisitor extends AbstractVisitor {
field.getArgs().add(constrArg); field.getArgs().add(constrArg);
} }
if (co.getClassType() != cls.getClassInfo()) { if (!co.getClassType().equals(classInfo)) {
// enum contains additional methods // enum contains additional methods
for (ClassNode innerCls : cls.getInnerClasses()) { for (ClassNode innerCls : cls.getInnerClasses()) {
if (innerCls.getClassInfo().equals(co.getClassType())) { if (innerCls.getClassInfo().equals(co.getClassType())) {
......
package jadx.tests.integration.enums;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsLines;
import static org.junit.Assert.assertThat;
public class TestEnumsWithConsts extends IntegrationTest {
public static class TestCls {
public static final int C1 = 1;
public static final int C2 = 2;
public static final int C4 = 4;
public static final String S = "NORTH";
public enum Direction {
NORTH,
SOUTH,
EAST,
WEST
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsLines(1, "public enum Direction {",
indent(1) + "NORTH,",
indent(1) + "SOUTH,",
indent(1) + "EAST,",
indent(1) + "WEST",
"}"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment