Skip to content

Commit 8b34b0d

Browse files
disable user renaming of enum constants
1 parent d54bbd6 commit 8b34b0d

File tree

7 files changed

+154
-42
lines changed

7 files changed

+154
-42
lines changed

enigma/src/main/java/org/quiltmc/enigma/api/EnigmaProject.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
import org.quiltmc.enigma.api.analysis.index.jar.EntryIndex;
88
import org.quiltmc.enigma.api.analysis.index.jar.JarIndex;
99
import org.quiltmc.enigma.api.analysis.index.mapping.MappingsIndex;
10+
import org.quiltmc.enigma.api.service.JarIndexerService;
1011
import org.quiltmc.enigma.api.service.ObfuscationTestService;
1112
import org.quiltmc.enigma.api.source.TokenType;
1213
import org.quiltmc.enigma.api.translation.mapping.EntryResolver;
1314
import org.quiltmc.enigma.api.translation.mapping.ResolutionStrategy;
1415
import org.quiltmc.enigma.api.translation.mapping.tree.EntryTreeUtil;
1516
import org.quiltmc.enigma.api.translation.mapping.tree.HashEntryTree;
17+
import org.quiltmc.enigma.api.translation.representation.entry.FieldEntry;
1618
import org.quiltmc.enigma.impl.bytecode.translator.TranslationClassVisitor;
1719
import org.quiltmc.enigma.api.class_provider.ClassProvider;
1820
import org.quiltmc.enigma.api.class_provider.ObfuscationFixClassProvider;
@@ -22,6 +24,7 @@
2224
import org.quiltmc.enigma.api.translation.Translator;
2325
import org.quiltmc.enigma.api.translation.mapping.EntryMapping;
2426
import org.quiltmc.enigma.api.translation.mapping.EntryRemapper;
27+
import org.quiltmc.enigma.impl.plugin.EnumConstantIndexingService;
2528
import org.quiltmc.enigma.impl.translation.mapping.MappingsChecker;
2629
import org.quiltmc.enigma.api.translation.mapping.tree.DeltaTrackingTree;
2730
import org.quiltmc.enigma.api.translation.mapping.tree.EntryTree;
@@ -48,6 +51,7 @@
4851
import java.util.Map;
4952
import java.util.Objects;
5053
import java.util.Set;
54+
import java.util.Optional;
5155
import java.util.concurrent.atomic.AtomicInteger;
5256
import java.util.jar.JarEntry;
5357
import java.util.jar.JarOutputStream;
@@ -190,7 +194,7 @@ public boolean isNavigable(Entry<?> obfEntry) {
190194
return this.jarIndex.getIndex(EntryIndex.class).hasEntry(obfEntry);
191195
}
192196

193-
public boolean isRenamable(Entry<?> obfEntry) {
197+
public boolean isInternallyRenamable(Entry<?> obfEntry) {
194198
if (obfEntry instanceof MethodEntry obfMethodEntry) {
195199
// constructors are not renamable!
196200
if (obfMethodEntry.isConstructor()) {
@@ -218,9 +222,11 @@ public boolean isRenamable(Entry<?> obfEntry) {
218222
if (this.isLibraryMethodOverride(obfMethodEntry)) {
219223
return false;
220224
}
221-
} else if (obfEntry instanceof LocalVariableEntry localEntry && !localEntry.isArgument()) {
222-
return false;
223-
} else if (obfEntry instanceof LocalVariableEntry localEntry && localEntry.isArgument()) {
225+
} else if (obfEntry instanceof LocalVariableEntry localEntry) {
226+
if (!localEntry.isArgument()) {
227+
return false;
228+
}
229+
224230
MethodEntry method = localEntry.getParent();
225231
ClassDefEntry parent = this.jarIndex.getIndex(EntryIndex.class).getDefinition(method.getParent());
226232

@@ -265,10 +271,34 @@ private boolean isLibraryMethodOverride(MethodEntry methodEntry) {
265271
}
266272
}
267273

274+
public boolean isRenamable(Entry<?> obfEntry) {
275+
if (this.isInternallyRenamable(obfEntry)) {
276+
if (obfEntry instanceof FieldEntry fieldEntry) {
277+
return !this.getEnumConstantIndexingService()
278+
.map(service -> service.isEnumConstant(fieldEntry))
279+
.orElse(false);
280+
} else {
281+
return true;
282+
}
283+
} else {
284+
return false;
285+
}
286+
}
287+
288+
private Optional<EnumConstantIndexingService> getEnumConstantIndexingService() {
289+
return this.getEnigma()
290+
.getService(JarIndexerService.TYPE, EnumConstantIndexingService.ID)
291+
.map(service -> (EnumConstantIndexingService) service);
292+
}
293+
268294
private static boolean isEnumValueOfMethod(ClassDefEntry parent, MethodEntry method) {
269295
return parent != null && parent.isEnum() && method.getName().equals("valueOf") && method.getDesc().toString().equals("(Ljava/lang/String;)L" + parent.getFullName() + ";");
270296
}
271297

298+
public boolean isInternallyRenamable(EntryReference<Entry<?>, Entry<?>> obfReference) {
299+
return obfReference.isNamed() && this.isInternallyRenamable(obfReference.getNameableEntry());
300+
}
301+
272302
public boolean isRenamable(EntryReference<Entry<?>, Entry<?>> obfReference) {
273303
return obfReference.isNamed() && this.isRenamable(obfReference.getNameableEntry());
274304
}

enigma/src/main/java/org/quiltmc/enigma/api/analysis/tree/StructureTreeNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ public void load(EnigmaProject project, StructureTreeOptions options) {
4444
case ALL -> children;
4545
case OBFUSCATED -> children
4646
// remove deobfuscated members if only obfuscated, unless it's an inner class
47-
.filter(e -> (e instanceof ClassEntry) || (project.isObfuscated(e) && project.isRenamable(e)))
47+
.filter(e -> (e instanceof ClassEntry) || (project.isObfuscated(e) && project.isInternallyRenamable(e)))
4848
// keep constructor methods if the class is obfuscated
4949
.filter(e -> !(e instanceof MethodEntry m && m.isConstructor()) || project.isObfuscated(e.getParent()));
5050
case DEOBFUSCATED -> children.filter(e -> (e instanceof ClassEntry)
51-
|| (!project.isObfuscated(e) && project.isRenamable(e))
51+
|| (!project.isObfuscated(e) && project.isInternallyRenamable(e))
5252
// keep constructor methods if the class is deobfuscated
5353
|| (e instanceof MethodEntry m && m.isConstructor()) && !project.isObfuscated(e.getParent()));
5454
};

enigma/src/main/java/org/quiltmc/enigma/api/source/DecompiledClassSource.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ private String remapToken(TokenStore target, EnigmaProject project, Token token,
6464
} else {
6565
target.add(project, EntryMapping.OBFUSCATED, movedToken);
6666
}
67+
} else if (project.isInternallyRenamable(reference)) {
68+
if (translatedEntry != null && !translatedEntry.isObfuscated()) {
69+
return translatedEntry.getValue().getSourceRemapName();
70+
}
6771
} else if (DEBUG_TOKEN_HIGHLIGHTS) {
6872
target.add(project, new EntryMapping(null, null, TokenType.DEBUG, null), movedToken);
6973
}

enigma/src/main/java/org/quiltmc/enigma/impl/plugin/BuiltinPlugin.java

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import org.quiltmc.enigma.api.analysis.index.jar.BridgeMethodIndex;
55
import org.quiltmc.enigma.api.EnigmaPlugin;
66
import org.quiltmc.enigma.api.EnigmaPluginContext;
7-
import org.quiltmc.enigma.api.analysis.index.jar.EntryIndex;
87
import org.quiltmc.enigma.api.analysis.index.jar.JarIndex;
98
import org.quiltmc.enigma.api.service.JarIndexerService;
109
import org.quiltmc.enigma.api.service.NameProposalService;
@@ -30,35 +29,10 @@ public void init(EnigmaPluginContext ctx) {
3029
}
3130

3231
private static void registerEnumNamingService(EnigmaPluginContext ctx) {
33-
final Map<Entry<?>, String> names = new HashMap<>();
34-
final EnumFieldNameFindingVisitor visitor = new EnumFieldNameFindingVisitor(names);
32+
final EnumFieldNameFindingVisitor visitor = new EnumFieldNameFindingVisitor();
3533

36-
ctx.registerService(JarIndexerService.TYPE, ctx1 -> JarIndexerService.fromVisitor(visitor, "enigma:enum_initializer_indexer"));
37-
38-
ctx.registerService(NameProposalService.TYPE, ctx1 -> new NameProposalService() {
39-
@Override
40-
public Map<Entry<?>, EntryMapping> getProposedNames(Enigma enigma, JarIndex index) {
41-
Map<Entry<?>, EntryMapping> mappings = new HashMap<>();
42-
43-
index.getIndex(EntryIndex.class).getFields().forEach(field -> {
44-
if (names.containsKey(field)) {
45-
mappings.put(field, this.createMapping(names.get(field), TokenType.JAR_PROPOSED));
46-
}
47-
});
48-
49-
return mappings;
50-
}
51-
52-
@Override
53-
public Map<Entry<?>, EntryMapping> getDynamicProposedNames(EntryRemapper remapper, @Nullable Entry<?> obfEntry, @Nullable EntryMapping oldMapping, @Nullable EntryMapping newMapping) {
54-
return null;
55-
}
56-
57-
@Override
58-
public String getId() {
59-
return "enigma:enum_name_proposer";
60-
}
61-
});
34+
ctx.registerService(JarIndexerService.TYPE, ctx1 -> new EnumConstantIndexingService(visitor));
35+
ctx.registerService(NameProposalService.TYPE, ctx1 -> new EnumConstantProposalService(visitor));
6236
}
6337

6438
private static void registerRecordNamingService(EnigmaPluginContext ctx) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.quiltmc.enigma.impl.plugin;
2+
3+
import org.objectweb.asm.tree.ClassNode;
4+
import org.quiltmc.enigma.api.analysis.index.jar.JarIndex;
5+
import org.quiltmc.enigma.api.class_provider.ProjectClassProvider;
6+
import org.quiltmc.enigma.api.service.JarIndexerService;
7+
import org.quiltmc.enigma.api.translation.representation.entry.FieldEntry;
8+
9+
import javax.annotation.Nullable;
10+
import java.util.Set;
11+
12+
public class EnumConstantIndexingService implements JarIndexerService {
13+
public static final String ID = "enigma:enum_initializer_indexer";
14+
15+
private final EnumFieldNameFindingVisitor visitor;
16+
17+
EnumConstantIndexingService(EnumFieldNameFindingVisitor visitor) {
18+
this.visitor = visitor;
19+
}
20+
21+
@Override
22+
public void acceptJar(Set<String> scope, ProjectClassProvider classProvider, JarIndex jarIndex) {
23+
for (String className : scope) {
24+
ClassNode node = classProvider.get(className);
25+
if (node != null) {
26+
node.accept(this.visitor);
27+
}
28+
}
29+
}
30+
31+
@Override
32+
public String getId() {
33+
return ID;
34+
}
35+
36+
public boolean isEnumConstant(FieldEntry field) {
37+
return this.visitor.isEnumConstant(field);
38+
}
39+
40+
@Nullable
41+
public String getEnumConstantName(FieldEntry field) {
42+
return this.visitor.getEnumConstantName(field);
43+
}
44+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.quiltmc.enigma.impl.plugin;
2+
3+
import org.quiltmc.enigma.api.Enigma;
4+
import org.quiltmc.enigma.api.analysis.index.jar.EntryIndex;
5+
import org.quiltmc.enigma.api.analysis.index.jar.JarIndex;
6+
import org.quiltmc.enigma.api.service.NameProposalService;
7+
import org.quiltmc.enigma.api.source.TokenType;
8+
import org.quiltmc.enigma.api.translation.mapping.EntryMapping;
9+
import org.quiltmc.enigma.api.translation.mapping.EntryRemapper;
10+
import org.quiltmc.enigma.api.translation.representation.entry.Entry;
11+
12+
import javax.annotation.Nullable;
13+
import java.util.HashMap;
14+
import java.util.Map;
15+
16+
public class EnumConstantProposalService implements NameProposalService {
17+
private final EnumFieldNameFindingVisitor visitor;
18+
19+
EnumConstantProposalService(EnumFieldNameFindingVisitor visitor) {
20+
this.visitor = visitor;
21+
}
22+
23+
@Override
24+
public Map<Entry<?>, EntryMapping> getProposedNames(Enigma enigma, JarIndex index) {
25+
Map<Entry<?>, EntryMapping> mappings = new HashMap<>();
26+
27+
index.getIndex(EntryIndex.class).getFields().forEach(field -> {
28+
final String name = this.visitor.getEnumConstantName(field);
29+
if (name != null) {
30+
mappings.put(field, this.createMapping(name, TokenType.JAR_PROPOSED));
31+
}
32+
});
33+
34+
return mappings;
35+
}
36+
37+
@Override
38+
public Map<Entry<?>, EntryMapping> getDynamicProposedNames(
39+
EntryRemapper remapper, @Nullable Entry<?> obfEntry, @Nullable EntryMapping oldMapping,
40+
@Nullable EntryMapping newMapping
41+
) {
42+
return null;
43+
}
44+
45+
@Override
46+
public String getId() {
47+
return "enigma:enum_name_proposer";
48+
}
49+
}

enigma/src/main/java/org/quiltmc/enigma/impl/plugin/EnumFieldNameFindingVisitor.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
import org.quiltmc.enigma.api.Enigma;
1919
import org.quiltmc.enigma.api.translation.representation.TypeDescriptor;
2020
import org.quiltmc.enigma.api.translation.representation.entry.ClassEntry;
21-
import org.quiltmc.enigma.api.translation.representation.entry.Entry;
2221
import org.quiltmc.enigma.api.translation.representation.entry.FieldEntry;
2322

23+
import javax.annotation.Nullable;
2424
import java.util.ArrayList;
25+
import java.util.HashMap;
2526
import java.util.HashSet;
2627
import java.util.List;
2728
import java.util.Map;
@@ -30,22 +31,20 @@
3031
final class EnumFieldNameFindingVisitor extends ClassVisitor {
3132
private ClassEntry clazz;
3233
private String className;
33-
private final Map<Entry<?>, String> mappings;
34+
private final Map<FieldEntry, String> enumConstants;
3435
private final Set<Pair<String, String>> enumFields = new HashSet<>();
3536
private final List<MethodNode> classInits = new ArrayList<>();
3637

37-
EnumFieldNameFindingVisitor(Map<Entry<?>, String> mappings) {
38+
EnumFieldNameFindingVisitor() {
3839
super(Enigma.ASM_VERSION);
39-
this.mappings = mappings;
40+
this.enumConstants = new HashMap<>();
4041
}
4142

4243
@Override
4344
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
4445
super.visit(version, access, name, signature, superName, interfaces);
4546
this.className = name;
4647
this.clazz = new ClassEntry(name);
47-
this.enumFields.clear();
48-
this.classInits.clear();
4948
}
5049

5150
@Override
@@ -76,9 +75,21 @@ public void visitEnd() {
7675
this.collectResults();
7776
} catch (Exception ex) {
7877
throw new RuntimeException(ex);
78+
} finally {
79+
this.enumFields.clear();
80+
this.classInits.clear();
7981
}
8082
}
8183

84+
public boolean isEnumConstant(FieldEntry field) {
85+
return this.enumConstants.containsKey(field);
86+
}
87+
88+
@Nullable
89+
public String getEnumConstantName(FieldEntry field) {
90+
return this.enumConstants.get(field);
91+
}
92+
8293
private void collectResults() throws Exception {
8394
String owner = this.className;
8495
Analyzer<SourceValue> analyzer = new Analyzer<>(new SourceInterpreter());
@@ -108,7 +119,7 @@ private void collectResults() throws Exception {
108119
}
109120

110121
if (s != null) {
111-
this.mappings.put(new FieldEntry(this.clazz, ((FieldInsnNode) instr2).name, new TypeDescriptor(((FieldInsnNode) instr2).desc)), s);
122+
this.enumConstants.put(new FieldEntry(this.clazz, ((FieldInsnNode) instr2).name, new TypeDescriptor(((FieldInsnNode) instr2).desc)), s);
112123
}
113124

114125
// report otherwise?

0 commit comments

Comments
 (0)