summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java
diff options
context:
space:
mode:
authorGravatar Runemoro2019-11-02 17:23:14 -0400
committerGravatar modmuss502019-11-02 21:23:14 +0000
commit422b10b419eb010b612931e8b250b9dd1b7424ed (patch)
treeb9c1d3a7add5b8d01d5b0196d6c29ad00273987c /src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java
parentFix array class translation (#173) (diff)
downloadenigma-fork-422b10b419eb010b612931e8b250b9dd1b7424ed.tar.gz
enigma-fork-422b10b419eb010b612931e8b250b9dd1b7424ed.tar.xz
enigma-fork-422b10b419eb010b612931e8b250b9dd1b7424ed.zip
Check protected method/field target in visibility index (#157)
Diffstat (limited to 'src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java')
-rw-r--r--src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java b/src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java
new file mode 100644
index 0000000..da2b5ef
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java
@@ -0,0 +1,153 @@
1package cuchaz.enigma.analysis;
2
3import cuchaz.enigma.analysis.index.EntryIndex;
4import cuchaz.enigma.analysis.index.InheritanceIndex;
5import cuchaz.enigma.translation.representation.AccessFlags;
6import cuchaz.enigma.translation.representation.entry.ClassDefEntry;
7import cuchaz.enigma.translation.representation.entry.ClassEntry;
8import org.objectweb.asm.Type;
9import org.objectweb.asm.tree.analysis.BasicValue;
10import org.objectweb.asm.tree.analysis.SimpleVerifier;
11
12import java.util.Set;
13
14public class IndexSimpleVerifier extends SimpleVerifier {
15 private static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
16 private final EntryIndex entryIndex;
17 private final InheritanceIndex inheritanceIndex;
18
19 public IndexSimpleVerifier(EntryIndex entryIndex, InheritanceIndex inheritanceIndex) {
20 super(ASM7, null, null, null, false);
21 this.entryIndex = entryIndex;
22 this.inheritanceIndex = inheritanceIndex;
23 }
24
25 @Override
26 protected boolean isSubTypeOf(BasicValue value, BasicValue expected) {
27 Type expectedType = expected.getType();
28 Type type = value.getType();
29 switch (expectedType.getSort()) {
30 case Type.INT:
31 case Type.FLOAT:
32 case Type.LONG:
33 case Type.DOUBLE:
34 return type.equals(expectedType);
35 case Type.ARRAY:
36 case Type.OBJECT:
37 if (type.equals(NULL_TYPE)) {
38 return true;
39 } else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
40 if (isAssignableFrom(expectedType, type)) {
41 return true;
42 } else if (isInterface(expectedType)) {
43 return isAssignableFrom(OBJECT_TYPE, type);
44 } else {
45 return false;
46 }
47 } else {
48 return false;
49 }
50 default:
51 throw new AssertionError();
52 }
53 }
54
55 @Override
56 protected boolean isInterface(Type type) {
57 AccessFlags classAccess = entryIndex.getClassAccess(new ClassEntry(type.getInternalName()));
58 if (classAccess != null) {
59 return classAccess.isInterface();
60 }
61
62 Class<?> clazz = getClass(type);
63 if (clazz != null) {
64 return clazz.isInterface();
65 }
66
67 return false;
68 }
69
70 @Override
71 protected Type getSuperClass(Type type) {
72 ClassDefEntry definition = entryIndex.getDefinition(new ClassEntry(type.getInternalName()));
73 if (definition != null) {
74 return Type.getType('L' + definition.getSuperClass().getFullName() + ';');
75 }
76
77 Class<?> clazz = getClass(type);
78 if (clazz != null) {
79 return Type.getType(clazz.getSuperclass());
80 }
81
82 return OBJECT_TYPE;
83 }
84
85 @Override
86 protected boolean isAssignableFrom(Type type1, Type type2) {
87 if (type1.equals(type2)) {
88 return true;
89 }
90
91 if (type2.equals(NULL_TYPE)) {
92 return true;
93 }
94
95 if (type1.getSort() == Type.ARRAY) {
96 return type2.getSort() == Type.ARRAY && isAssignableFrom(Type.getType(type1.getDescriptor().substring(1)), Type.getType(type2.getDescriptor().substring(1)));
97 }
98
99 if (type2.getSort() == Type.ARRAY) {
100 return type1.equals(OBJECT_TYPE);
101 }
102
103 if (type1.getSort() == Type.OBJECT && type2.getSort() == Type.OBJECT) {
104 if (type1.equals(OBJECT_TYPE)) {
105 return true;
106 }
107
108 ClassEntry class1 = new ClassEntry(type1.getInternalName());
109 ClassEntry class2 = new ClassEntry(type2.getInternalName());
110
111 if (entryIndex.hasClass(class1) && entryIndex.hasClass(class2)) {
112 return inheritanceIndex.getAncestors(class2).contains(class1);
113 }
114
115 Class<?> class1Class = getClass(Type.getType('L' + class1.getFullName() + ';'));
116 Class<?> class2Class = getClass(Type.getType('L' + class2.getFullName() + ';'));
117
118 if (class1Class == null) {
119 return true; // missing classes to find out
120 }
121
122 if (class2Class != null) {
123 return class1Class.isAssignableFrom(class2Class);
124 }
125
126 if (entryIndex.hasClass(class2)) {
127 Set<ClassEntry> ancestors = inheritanceIndex.getAncestors(class2);
128
129 for (ClassEntry ancestorEntry : ancestors) {
130 Class<?> ancestor = getClass(Type.getType('L' + ancestorEntry.getFullName() + ';'));
131 if (ancestor == null || class1Class.isAssignableFrom(ancestor)) {
132 return true; // assignable, or missing classes to find out
133 }
134 }
135
136 return false;
137 }
138
139 return true; // missing classes to find out
140 }
141
142 return false;
143 }
144
145 @Override
146 protected final Class<?> getClass(Type type) {
147 try {
148 return Class.forName(type.getSort() == Type.ARRAY ? type.getDescriptor().replace('/', '.') : type.getClassName(), false, null);
149 } catch (ClassNotFoundException e) {
150 return null;
151 }
152 }
153}