Skip to content

Commit 3755e1a

Browse files
committed
feat: working pure function analysis hash
1 parent ee95cde commit 3755e1a

23 files changed

Lines changed: 1012 additions & 1169 deletions

File tree

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ allprojects {
88
jcenter()
99
mavenCentral()
1010
mavenLocal()
11+
maven {
12+
url 'https://repo.cleanroommc.com/releases/'
13+
}
1114
}
1215

1316
apply plugin: 'java'

dev.skidfuscator.obfuscator.pureanalysis/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ version = '2.0.0-SNAPSHOT'
77

88
repositories {
99
mavenCentral()
10+
maven { url 'https://jitpack.io' }
1011
}
1112

1213
dependencies {
1314
api project(':modasm')
15+
api 'com.github.xxDark:SSVM:d559ea90bb'
1416

1517
testImplementation platform('org.junit:junit-bom:5.10.0')
1618
testImplementation 'org.junit.jupiter:junit-jupiter'
Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,12 @@
11
package dev.skidfuscator.pureanalysis;
22

3-
import org.objectweb.asm.ClassReader;
43
import org.objectweb.asm.tree.ClassNode;
54

65
import java.io.IOException;
7-
import java.util.HashSet;
86
import java.util.Set;
9-
import java.util.concurrent.ConcurrentHashMap;
107

11-
public class ClassHierarchyAnalyzer {
12-
private final ConcurrentHashMap<String, ClassNode> classCache = new ConcurrentHashMap<>();
13-
private final ClassLoader classLoader;
14-
private final Set<String> analyzedClasses = ConcurrentHashMap.newKeySet();
15-
16-
public ClassHierarchyAnalyzer(ClassLoader classLoader) {
17-
this.classLoader = classLoader;
18-
}
19-
20-
public ClassNode getClass(String className) throws IOException {
21-
return classCache.computeIfAbsent(className, this::loadClass);
22-
}
23-
24-
private ClassNode loadClass(String className) {
25-
try {
26-
ClassReader reader = new ClassReader(classLoader.getResourceAsStream(
27-
className.replace('.', '/') + ".class"));
28-
ClassNode classNode = new ClassNode();
29-
reader.accept(classNode, ClassReader.EXPAND_FRAMES);
30-
return classNode;
31-
} catch (IOException e) {
32-
throw new RuntimeException("Failed to load class: " + className, e);
33-
}
34-
}
35-
36-
public Set<String> getAllSuperClasses(String className) throws IOException {
37-
Set<String> superClasses = new HashSet<>();
38-
collectSuperClasses(className, superClasses);
39-
return superClasses;
40-
}
41-
42-
private void collectSuperClasses(String className, Set<String> collected) throws IOException {
43-
if (className == null || className.equals("java/lang/Object")) return;
44-
45-
ClassNode classNode = getClass(className);
46-
collected.add(className);
47-
48-
// Collect superclass
49-
if (classNode.superName != null) {
50-
collectSuperClasses(classNode.superName, collected);
51-
}
52-
53-
// Collect interfaces
54-
for (String interfaceName : classNode.interfaces) {
55-
collectSuperClasses(interfaceName, collected);
56-
}
57-
}
58-
}
8+
public interface ClassHierarchyAnalyzer {
9+
ClassNode getClass(String className) throws IOException;
10+
11+
Set<String> getAllSuperClasses(String className) throws IOException;
12+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package dev.skidfuscator.pureanalysis;
2+
3+
import org.objectweb.asm.ClassReader;
4+
import org.objectweb.asm.tree.ClassNode;
5+
6+
import java.io.IOException;
7+
import java.util.HashSet;
8+
import java.util.Set;
9+
import java.util.concurrent.ConcurrentHashMap;
10+
11+
public class SimpleClassHierarchyAnalyzer implements ClassHierarchyAnalyzer {
12+
private final ConcurrentHashMap<String, ClassNode> classCache = new ConcurrentHashMap<>();
13+
private final ClassLoader classLoader;
14+
private final Set<String> analyzedClasses = ConcurrentHashMap.newKeySet();
15+
16+
public SimpleClassHierarchyAnalyzer(ClassLoader classLoader) {
17+
this.classLoader = classLoader;
18+
}
19+
20+
@Override
21+
public ClassNode getClass(String className) throws IOException {
22+
return classCache.computeIfAbsent(className, this::loadClass);
23+
}
24+
25+
private ClassNode loadClass(String className) {
26+
try {
27+
ClassReader reader = new ClassReader(classLoader.getResourceAsStream(
28+
className.replace('.', '/') + ".class"));
29+
ClassNode classNode = new ClassNode();
30+
reader.accept(classNode, ClassReader.EXPAND_FRAMES);
31+
return classNode;
32+
} catch (IOException e) {
33+
throw new RuntimeException("Failed to load class: " + className, e);
34+
}
35+
}
36+
37+
@Override
38+
public Set<String> getAllSuperClasses(String className) throws IOException {
39+
Set<String> superClasses = new HashSet<>();
40+
collectSuperClasses(className, superClasses);
41+
return superClasses;
42+
}
43+
44+
private void collectSuperClasses(String className, Set<String> collected) throws IOException {
45+
if (className == null || className.equals("java/lang/Object")) return;
46+
47+
ClassNode classNode = getClass(className);
48+
collected.add(className);
49+
50+
// Collect superclass
51+
if (classNode.superName != null) {
52+
collectSuperClasses(classNode.superName, collected);
53+
}
54+
55+
// Collect interfaces
56+
for (String interfaceName : classNode.interfaces) {
57+
collectSuperClasses(interfaceName, collected);
58+
}
59+
}
60+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dev.skidfuscator.pureanalysis.vm;
2+
3+
import org.objectweb.asm.Type;
4+
import org.objectweb.asm.tree.MethodNode;
5+
6+
public class VirtualMachinery {
7+
8+
9+
public static class VirtualMachineReport {
10+
private MethodNode method;
11+
}
12+
}

dev.skidfuscator.obfuscator.pureanalysis/src/test/java/JVMPurityAnalyzerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import dev.skidfuscator.pureanalysis.ClassHierarchyAnalyzer;
21
import dev.skidfuscator.pureanalysis.PurityAnalyzer;
32
import dev.skidfuscator.pureanalysis.PurityReport;
3+
import dev.skidfuscator.pureanalysis.SimpleClassHierarchyAnalyzer;
44
import org.junit.jupiter.api.BeforeEach;
55
import org.junit.jupiter.api.Test;
66
import org.objectweb.asm.ClassReader;
@@ -23,7 +23,7 @@ public class JVMPurityAnalyzerTest {
2323

2424
@BeforeEach
2525
void setUp() {
26-
analyzer = new PurityAnalyzer(new ClassHierarchyAnalyzer(
26+
analyzer = new PurityAnalyzer(new SimpleClassHierarchyAnalyzer(
2727
getClass().getClassLoader())
2828
);
2929
}

dev.skidfuscator.obfuscator.pureanalysis/src/test/java/framework/PurityAnalysisTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package framework;
22

3-
import dev.skidfuscator.pureanalysis.ClassHierarchyAnalyzer;
43
import dev.skidfuscator.pureanalysis.PurityAnalyzer;
54
import dev.skidfuscator.pureanalysis.PurityReport;
5+
import dev.skidfuscator.pureanalysis.SimpleClassHierarchyAnalyzer;
66
import org.junit.jupiter.api.DynamicTest;
77
import org.junit.jupiter.api.TestFactory;
88
import org.objectweb.asm.ClassReader;
@@ -35,7 +35,7 @@ public class PurityAnalysisTest {
3535
private final MemoryClassLoader classLoader = new MemoryClassLoader();
3636

3737
public PurityAnalysisTest() {
38-
this.analyzer = new PurityAnalyzer(new ClassHierarchyAnalyzer(classLoader));
38+
this.analyzer = new PurityAnalyzer(new SimpleClassHierarchyAnalyzer(classLoader));
3939
setupAnalyzer();
4040
}
4141

dev.skidfuscator.obfuscator/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ dependencies {
1717
compileOnly 'org.projectlombok:lombok:1.18.24'
1818

1919
api project(':commons')
20+
api project(':pure-analysis')
21+
2022
implementation 'com.github.lukfor:magic-progress:0.3.2'
2123
implementation 'com.github.matomo-org:matomo-java-tracker:v1.7'
2224
api 'com.github.Col-E:jphantom:1.4.3'

0 commit comments

Comments
 (0)