From 2dc7428e37bdd7a119f53d02ce157675509b0d63 Mon Sep 17 00:00:00 2001 From: jeff Date: Mon, 23 Feb 2015 23:29:22 -0500 Subject: lots of work in better handling of inner classes also working on recognizing unobfuscated and deobfuscated jars (needed for M3L) --- test/cuchaz/enigma/TestInnerClasses.java | 67 ++++++++++++++++++---- test/cuchaz/enigma/TestJarIndexLoneClass.java | 7 +-- test/cuchaz/enigma/TestTranslator.java | 36 ++++++++++++ .../enigma/inputs/innerClasses/F_ClassTree.java | 20 +++++++ .../enigma/inputs/translation/F_ObjectMethods.java | 19 ------ .../enigma/inputs/translation/G_ObjectMethods.java | 19 ++++++ .../enigma/inputs/translation/H_OuterClass.java | 26 +++++++++ .../enigma/inputs/translation/M_NamelessClass.java | 26 +++++++++ test/cuchaz/enigma/resources/translation.mappings | 12 ++++ 9 files changed, 197 insertions(+), 35 deletions(-) create mode 100644 test/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java delete mode 100644 test/cuchaz/enigma/inputs/translation/F_ObjectMethods.java create mode 100644 test/cuchaz/enigma/inputs/translation/G_ObjectMethods.java create mode 100644 test/cuchaz/enigma/inputs/translation/H_OuterClass.java create mode 100644 test/cuchaz/enigma/inputs/translation/M_NamelessClass.java (limited to 'test') diff --git a/test/cuchaz/enigma/TestInnerClasses.java b/test/cuchaz/enigma/TestInnerClasses.java index 2e16a33..2eb5acc 100644 --- a/test/cuchaz/enigma/TestInnerClasses.java +++ b/test/cuchaz/enigma/TestInnerClasses.java @@ -18,23 +18,30 @@ import java.util.jar.JarFile; import org.junit.Test; +import static cuchaz.enigma.TestEntryFactory.*; + import cuchaz.enigma.analysis.JarIndex; +import cuchaz.enigma.mapping.ClassEntry; public class TestInnerClasses { private JarIndex m_index; private Deobfuscator m_deobfuscator; - private static final String AnonymousOuter = "none/a"; - private static final String AnonymousInner = "b"; - private static final String SimpleOuter = "none/g"; - private static final String SimpleInner = "h"; - private static final String ConstructorArgsOuter = "none/e"; - private static final String ConstructorArgsInner = "f"; - private static final String AnonymousWithScopeArgsOuter = "none/c"; - private static final String AnonymousWithScopeArgsInner = "d"; - private static final String AnonymousWithOuterAccessOuter = "none/i"; - private static final String AnonymousWithOuterAccessInner = "j"; + private static final ClassEntry AnonymousOuter = newClass("none/a"); + private static final ClassEntry AnonymousInner = newClass("none/b"); + private static final ClassEntry SimpleOuter = newClass("none/g"); + private static final ClassEntry SimpleInner = newClass("none/h"); + private static final ClassEntry ConstructorArgsOuter = newClass("none/e"); + private static final ClassEntry ConstructorArgsInner = newClass("none/f"); + private static final ClassEntry AnonymousWithScopeArgsOuter = newClass("none/c"); + private static final ClassEntry AnonymousWithScopeArgsInner = newClass("none/d"); + private static final ClassEntry AnonymousWithOuterAccessOuter = newClass("none/i"); + private static final ClassEntry AnonymousWithOuterAccessInner = newClass("none/j"); + private static final ClassEntry ClassTreeRoot = newClass("none/k"); + private static final ClassEntry ClassTreeLevel1 = newClass("none/l"); + private static final ClassEntry ClassTreeLevel2 = newClass("none/m"); + private static final ClassEntry ClassTreeLevel3 = newClass("none/n"); public TestInnerClasses() throws Exception { @@ -84,7 +91,43 @@ public class TestInnerClasses { decompile(AnonymousWithOuterAccessOuter); } - private void decompile(String name) { - m_deobfuscator.getSourceTree(name); + @Test + public void classTree() { + + // root level + assertThat(m_index.containsObfClass(ClassTreeRoot), is(true)); + assertThat(m_index.getOuterClass(ClassTreeRoot), is(nullValue())); + assertThat(m_index.getInnerClasses(ClassTreeRoot), containsInAnyOrder(ClassTreeLevel1)); + + // level 1 + ClassEntry fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getSimpleName() + ); + assertThat(m_index.containsObfClass(fullClassEntry), is(true)); + assertThat(m_index.getOuterClass(ClassTreeLevel1), is(ClassTreeRoot)); + assertThat(m_index.getInnerClasses(ClassTreeLevel1), containsInAnyOrder(ClassTreeLevel2)); + + // level 2 + fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getSimpleName() + + "$" + ClassTreeLevel2.getSimpleName() + ); + assertThat(m_index.containsObfClass(fullClassEntry), is(true)); + assertThat(m_index.getOuterClass(ClassTreeLevel2), is(ClassTreeLevel1)); + assertThat(m_index.getInnerClasses(ClassTreeLevel2), containsInAnyOrder(ClassTreeLevel3)); + + // level 3 + fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getSimpleName() + + "$" + ClassTreeLevel2.getSimpleName() + + "$" + ClassTreeLevel3.getSimpleName() + ); + assertThat(m_index.containsObfClass(fullClassEntry), is(true)); + assertThat(m_index.getOuterClass(ClassTreeLevel3), is(ClassTreeLevel2)); + assertThat(m_index.getInnerClasses(ClassTreeLevel3), is(empty())); + } + + private void decompile(ClassEntry classEntry) { + m_deobfuscator.getSourceTree(classEntry.getName()); } } diff --git a/test/cuchaz/enigma/TestJarIndexLoneClass.java b/test/cuchaz/enigma/TestJarIndexLoneClass.java index 768284f..0c126ad 100644 --- a/test/cuchaz/enigma/TestJarIndexLoneClass.java +++ b/test/cuchaz/enigma/TestJarIndexLoneClass.java @@ -26,7 +26,6 @@ import cuchaz.enigma.analysis.ClassImplementationsTreeNode; import cuchaz.enigma.analysis.ClassInheritanceTreeNode; import cuchaz.enigma.analysis.EntryReference; import cuchaz.enigma.analysis.JarIndex; -import cuchaz.enigma.analysis.MethodImplementationsTreeNode; import cuchaz.enigma.analysis.MethodInheritanceTreeNode; import cuchaz.enigma.mapping.BehaviorEntry; import cuchaz.enigma.mapping.ClassEntry; @@ -125,17 +124,17 @@ public class TestJarIndexLoneClass { @Test public void innerClasses() { - assertThat(m_index.getInnerClasses("none/a"), is(empty())); + assertThat(m_index.getInnerClasses(newClass("none/a")), is(empty())); } @Test public void outerClass() { - assertThat(m_index.getOuterClass("a"), is(nullValue())); + assertThat(m_index.getOuterClass(newClass("a")), is(nullValue())); } @Test public void isAnonymousClass() { - assertThat(m_index.isAnonymousClass("none/a"), is(false)); + assertThat(m_index.isAnonymousClass(newClass("none/a")), is(false)); } @Test diff --git a/test/cuchaz/enigma/TestTranslator.java b/test/cuchaz/enigma/TestTranslator.java index 3fe1680..0252605 100644 --- a/test/cuchaz/enigma/TestTranslator.java +++ b/test/cuchaz/enigma/TestTranslator.java @@ -97,8 +97,44 @@ public class TestTranslator { assertMapping(newMethod("none/c", "b", "()I"), newMethod("deobf/C_SubClass", "m2", "()I")); } + @Test + public void innerClasses() { + + // classes + assertMapping(newClass("none/h"), newClass("deobf/H_OuterClass")); + assertMapping(newClass("none/h$i"), newClass("deobf/H_OuterClass$I_InnerClass")); + assertMapping(newClass("none/h$i$j"), newClass("deobf/H_OuterClass$I_InnerClass$J_InnerInnerClass")); + assertMapping(newClass("none/h$k"), newClass("deobf/H_OuterClass$k")); + assertMapping(newClass("none/h$k$l"), newClass("deobf/H_OuterClass$k$L_NamedInnerClass")); + + // fields + assertMapping(newField("none/h$i", "a", "I"), newField("deobf/H_OuterClass$I_InnerClass", "f1", "I")); + assertMapping(newField("none/h$i", "a", "Ljava/lang/String;"), newField("deobf/H_OuterClass$I_InnerClass", "f2", "Ljava/lang/String;")); + assertMapping(newField("none/h$i$j", "a", "I"), newField("deobf/H_OuterClass$I_InnerClass$J_InnerInnerClass", "f3", "I")); + assertMapping(newField("none/h$k$l", "a", "I"), newField("deobf/H_OuterClass$k$L_NamedInnerClass", "f4", "I")); + + // methods + assertMapping(newMethod("none/h$i", "a", "()V"), newMethod("deobf/H_OuterClass$I_InnerClass", "m1", "()V")); + assertMapping(newMethod("none/h$i$j", "a", "()V"), newMethod("deobf/H_OuterClass$I_InnerClass$J_InnerInnerClass", "m2", "()V")); + } + + @Test + public void namelessClass() { + assertMapping(newClass("none/m"), newClass("none/m")); + } + private void assertMapping(Entry obf, Entry deobf) { assertThat(m_deobfTranslator.translateEntry(obf), is(deobf)); assertThat(m_obfTranslator.translateEntry(deobf), is(obf)); + + String deobfName = m_deobfTranslator.translate(obf); + if (deobfName != null) { + assertThat(deobfName, is(deobf.getName())); + } + + String obfName = m_obfTranslator.translate(deobf); + if (obfName != null) { + assertThat(obfName, is(obf.getName())); + } } } diff --git a/test/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java b/test/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java new file mode 100644 index 0000000..6552d8a --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java @@ -0,0 +1,20 @@ +package cuchaz.enigma.inputs.innerClasses; + + +public class F_ClassTree { + + public class Level1 { + + public int f1; + + public class Level2 { + + public int f2; + + public class Level3 { + + public int f3; + } + } + } +} diff --git a/test/cuchaz/enigma/inputs/translation/F_ObjectMethods.java b/test/cuchaz/enigma/inputs/translation/F_ObjectMethods.java deleted file mode 100644 index 4e09179..0000000 --- a/test/cuchaz/enigma/inputs/translation/F_ObjectMethods.java +++ /dev/null @@ -1,19 +0,0 @@ -package cuchaz.enigma.inputs.translation; - -public class F_ObjectMethods { - - public void callEmAll() - throws Throwable { - clone(); - equals(this); - finalize(); - getClass(); - hashCode(); - notify(); - notifyAll(); - toString(); - wait(); - wait(0); - wait(0, 0); - } -} diff --git a/test/cuchaz/enigma/inputs/translation/G_ObjectMethods.java b/test/cuchaz/enigma/inputs/translation/G_ObjectMethods.java new file mode 100644 index 0000000..ebad5a3 --- /dev/null +++ b/test/cuchaz/enigma/inputs/translation/G_ObjectMethods.java @@ -0,0 +1,19 @@ +package cuchaz.enigma.inputs.translation; + +public class G_ObjectMethods { + + public void callEmAll() + throws Throwable { + clone(); + equals(this); + finalize(); + getClass(); + hashCode(); + notify(); + notifyAll(); + toString(); + wait(); + wait(0); + wait(0, 0); + } +} diff --git a/test/cuchaz/enigma/inputs/translation/H_OuterClass.java b/test/cuchaz/enigma/inputs/translation/H_OuterClass.java new file mode 100644 index 0000000..995c65d --- /dev/null +++ b/test/cuchaz/enigma/inputs/translation/H_OuterClass.java @@ -0,0 +1,26 @@ +package cuchaz.enigma.inputs.translation; + + +public class H_OuterClass { + + public class I_InnerClass { + + public int f1; + public String f2; + + public void m1() {} + + public class J_InnerInnerClass { + + public int f3; + + public void m2() {} + } + } + + public class K_NamelessClass { + public class L_NamedInnerClass { + public int f4; + } + } +} diff --git a/test/cuchaz/enigma/inputs/translation/M_NamelessClass.java b/test/cuchaz/enigma/inputs/translation/M_NamelessClass.java new file mode 100644 index 0000000..afc9a9a --- /dev/null +++ b/test/cuchaz/enigma/inputs/translation/M_NamelessClass.java @@ -0,0 +1,26 @@ +package cuchaz.enigma.inputs.translation; + + +public class M_NamelessClass { + + public class I_InnerClass { + + public int f1; + public String f2; + + public void m1() {} + + public class J_InnerInnerClass { + + public int f3; + + public void m2() {} + } + } + + public class K_NamelessClass { + public class L_NamedInnerClass { + public int f4; + } + } +} diff --git a/test/cuchaz/enigma/resources/translation.mappings b/test/cuchaz/enigma/resources/translation.mappings index d87d437..5dffaf1 100644 --- a/test/cuchaz/enigma/resources/translation.mappings +++ b/test/cuchaz/enigma/resources/translation.mappings @@ -17,3 +17,15 @@ CLASS none/c deobf/C_SubClass FIELD c f4 I METHOD a m1 ()I METHOD c m3 ()I +CLASS none/h deobf/H_OuterClass + CLASS none/i I_InnerClass + CLASS none/j J_InnerInnerClass + FIELD a f3 I + METHOD a m2 ()V + FIELD a f1 I + FIELD a f2 Ljava/lang/String; + METHOD a m1 ()V + CLASS none/k + CLASS none/l L_NamedInnerClass + FIELD a f4 I +CLASS none/m \ No newline at end of file -- cgit v1.2.3