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