From b73d303f3aca9610d3bad866518f21cc813a2c87 Mon Sep 17 00:00:00 2001 From: Julian Burner Date: Fri, 28 Apr 2023 13:14:32 +0200 Subject: Allow shadowing fields (#475) * Fix Enigma not allowing to shadow static fields * Fix mapping uniqueness verification * Allow shadowing any field * Fix a message Co-authored-by: ByMartrixx --- .../translation/mapping/MappingValidator.java | 47 +++++++++++++++++++++- .../representation/entry/ClassEntry.java | 5 +++ .../translation/representation/entry/Entry.java | 2 + .../representation/entry/FieldEntry.java | 7 +++- .../representation/entry/LocalVariableEntry.java | 5 +++ .../representation/entry/MethodEntry.java | 5 +++ .../cuchaz/enigma/utils/validation/Message.java | 2 + 7 files changed, 70 insertions(+), 3 deletions(-) (limited to 'enigma/src/main/java/cuchaz') diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java index 5f42373..f6c0a6b 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java @@ -4,10 +4,13 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; +import javax.annotation.Nullable; + import cuchaz.enigma.analysis.index.InheritanceIndex; import cuchaz.enigma.analysis.index.JarIndex; import cuchaz.enigma.translation.Translator; import cuchaz.enigma.translation.mapping.tree.EntryTree; +import cuchaz.enigma.translation.representation.AccessFlags; import cuchaz.enigma.translation.representation.entry.ClassEntry; import cuchaz.enigma.translation.representation.entry.Entry; import cuchaz.enigma.utils.validation.Message; @@ -41,12 +44,20 @@ public class MappingValidator { Collection relatedClasses = getRelatedClasses(containingClass); boolean error = false; + Entry shadowedEntry; for (ClassEntry relatedClass : relatedClasses) { + if (isStatic(entry) && relatedClass != containingClass) { + // static entries can only conflict with entries in the same class + continue; + } + Entry relatedEntry = entry.replaceAncestor(containingClass, relatedClass); Entry translatedEntry = deobfuscator.translate(relatedEntry); - List> translatedSiblings = obfToDeobf.getSiblings(relatedEntry).stream().map(deobfuscator::translate).toList(); + List> translatedSiblings = obfToDeobf.getSiblings(relatedEntry).stream() + .map(deobfuscator::translate) + .toList(); if (!isUnique(translatedEntry, translatedSiblings, name)) { Entry parent = translatedEntry.getParent(); @@ -58,6 +69,14 @@ public class MappingValidator { } error = true; + } else if ((shadowedEntry = getShadowedEntry(translatedEntry, translatedSiblings, name)) != null) { + Entry parent = shadowedEntry.getParent(); + + if (parent != null) { + vc.raise(Message.SHADOWED_NAME_CLASS, name, parent); + } else { + vc.raise(Message.SHADOWED_NAME, name); + } } } @@ -77,11 +96,35 @@ public class MappingValidator { private boolean isUnique(Entry entry, List> siblings, String name) { for (Entry sibling : siblings) { - if (entry.canConflictWith(sibling) && sibling.getName().equals(name)) { + if (canConflict(entry, sibling) && sibling.getName().equals(name)) { return false; } } return true; } + + private boolean canConflict(Entry entry, Entry sibling) { + return entry.canConflictWith(sibling); + } + + @Nullable + private Entry getShadowedEntry(Entry entry, List> siblings, String name) { + for (Entry sibling : siblings) { + if (canShadow(entry, sibling) && sibling.getName().equals(name)) { + return sibling; + } + } + + return null; + } + + private boolean canShadow(Entry entry, Entry sibling) { + return entry.canShadow(sibling); + } + + private boolean isStatic(Entry entry) { + AccessFlags accessFlags = index.getEntryIndex().getEntryAccess(entry); + return accessFlags != null && accessFlags.isStatic(); + } } diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java index be5f0b3..8659b40 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java @@ -121,6 +121,11 @@ public class ClassEntry extends ParentedEntry implements Comparable< return true; } + @Override + public boolean canShadow(Entry entry) { + return false; + } + @Override public void validateName(ValidationContext vc, String name) { IdentifierValidation.validateClassName(vc, name, this.isInnerClass()); diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java index 9615ca8..71425e0 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java @@ -108,6 +108,8 @@ public interface Entry

> extends Translatable { boolean canConflictWith(Entry entry); + boolean canShadow(Entry entry); + default ClassEntry getContainingClass() { ClassEntry last = null; Entry current = this; diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java index c1592a4..b4ad1ba 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java @@ -85,7 +85,12 @@ public class FieldEntry extends ParentedEntry implements Comparable< @Override public boolean canConflictWith(Entry entry) { - return entry instanceof FieldEntry && ((FieldEntry) entry).parent.equals(parent); + return false; + } + + @Override + public boolean canShadow(Entry entry) { + return entry instanceof FieldEntry; } @Override diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java index d22188b..9d0bbed 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java @@ -84,6 +84,11 @@ public class LocalVariableEntry extends ParentedEntry implements Co return entry instanceof LocalVariableEntry && ((LocalVariableEntry) entry).parent.equals(parent); } + @Override + public boolean canShadow(Entry entry) { + return false; + } + @Override public String toString() { return this.parent + "(" + this.index + ":" + this.name + ")"; diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java index 6fc3f0a..5ccb908 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java @@ -97,6 +97,11 @@ public class MethodEntry extends ParentedEntry implements Comparable return false; } + @Override + public boolean canShadow(Entry entry) { + return entry instanceof MethodEntry; + } + @Override public String toString() { return this.getFullName() + this.descriptor; diff --git a/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java b/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java index b7e67f2..9dbbb18 100644 --- a/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java +++ b/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java @@ -17,6 +17,8 @@ public class Message { public static final Message UNKNOWN_RECORD_GETTER = create(Type.ERROR, "unknown_record_getter"); public static final Message STYLE_VIOLATION = create(Type.WARNING, "style_violation"); + public static final Message SHADOWED_NAME_CLASS = create(Type.WARNING, "shadowed_name_class"); + public static final Message SHADOWED_NAME = create(Type.WARNING, "shadowed_name"); public final Type type; public final String textKey; -- cgit v1.2.3