1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.verifier.structurals;
18
19 import java.util.Arrays;
20
21 import org.apache.bcel.generic.ReferenceType;
22 import org.apache.bcel.generic.Type;
23 import org.apache.bcel.verifier.exc.AssertionViolatedException;
24 import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
25
26
27
28
29 public class LocalVariables implements Cloneable {
30
31
32 private final Type[] locals;
33
34
35
36
37
38
39 public LocalVariables(final int localVariableCount) {
40 locals = new Type[localVariableCount];
41 Arrays.fill(locals, Type.UNKNOWN);
42 }
43
44
45
46
47
48 @Override
49 public Object clone() {
50 final LocalVariables lvs = new LocalVariables(locals.length);
51 System.arraycopy(this.locals, 0, lvs.locals, 0, locals.length);
52 return lvs;
53 }
54
55
56
57
58 @Override
59 public boolean equals(final Object o) {
60 if (!(o instanceof LocalVariables)) {
61 return false;
62 }
63 final LocalVariables lv = (LocalVariables) o;
64 if (this.locals.length != lv.locals.length) {
65 return false;
66 }
67 for (int i = 0; i < this.locals.length; i++) {
68 if (!this.locals[i].equals(lv.locals[i])) {
69
70 return false;
71 }
72 }
73 return true;
74 }
75
76
77
78
79
80
81
82 public Type get(final int slotIndex) {
83 return locals[slotIndex];
84 }
85
86
87
88
89
90
91 public LocalVariables getClone() {
92 return (LocalVariables) this.clone();
93 }
94
95
96
97
98 @Override
99 public int hashCode() {
100 return locals.length;
101 }
102
103
104
105
106
107
108
109 public void initializeObject(final UninitializedObjectType uninitializedObjectType) {
110 for (int i = 0; i < locals.length; i++) {
111 if (locals[i] == uninitializedObjectType) {
112 locals[i] = uninitializedObjectType.getInitialized();
113 }
114 }
115 }
116
117
118
119
120
121
122 public int maxLocals() {
123 return locals.length;
124 }
125
126
127
128
129
130
131
132 public void merge(final LocalVariables localVariable) {
133
134 if (this.locals.length != localVariable.locals.length) {
135 throw new AssertionViolatedException("Merging LocalVariables of different size?!? From different methods or what?!?");
136 }
137
138 for (int i = 0; i < locals.length; i++) {
139 merge(localVariable, i);
140 }
141 }
142
143
144
145
146
147
148 private void merge(final LocalVariables lv, final int i) {
149 try {
150
151
152
153 if (!(locals[i] instanceof UninitializedObjectType) && lv.locals[i] instanceof UninitializedObjectType) {
154 throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
155 }
156
157 if (!locals[i].equals(lv.locals[i]) && locals[i] instanceof UninitializedObjectType && lv.locals[i] instanceof UninitializedObjectType) {
158 throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
159 }
160
161 if (locals[i] instanceof UninitializedObjectType && !(lv.locals[i] instanceof UninitializedObjectType)) {
162 locals[i] = ((UninitializedObjectType) locals[i]).getInitialized();
163 }
164 if (locals[i] instanceof ReferenceType && lv.locals[i] instanceof ReferenceType) {
165 if (!locals[i].equals(lv.locals[i])) {
166 final Type sup = ((ReferenceType) locals[i]).getFirstCommonSuperclass((ReferenceType) lv.locals[i]);
167
168 if (sup == null) {
169
170 throw new AssertionViolatedException("Could not load all the super classes of '" + locals[i] + "' and '" + lv.locals[i] + "'.");
171 }
172 locals[i] = sup;
173 }
174 } else if (!locals[i].equals(lv.locals[i])) {
175
176
177
178
179
180 locals[i] = Type.UNKNOWN;
181 }
182 } catch (final ClassNotFoundException e) {
183
184 throw new AssertionViolatedException("Missing class: " + e, e);
185 }
186 }
187
188
189
190
191
192
193
194 public void set(final int slotIndex, final Type type) {
195 if (type == Type.BYTE || type == Type.SHORT || type == Type.BOOLEAN || type == Type.CHAR) {
196 throw new AssertionViolatedException("LocalVariables do not know about '" + type + "'. Use Type.INT instead.");
197 }
198 locals[slotIndex] = type;
199 }
200
201
202
203
204 @Override
205 public String toString() {
206 final StringBuilder sb = new StringBuilder();
207 for (int i = 0; i < locals.length; i++) {
208 sb.append(Integer.toString(i));
209 sb.append(": ");
210 sb.append(locals[i]);
211 sb.append("\n");
212 }
213 return sb.toString();
214 }
215 }