7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.classfile.impl.verifier;
26
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Object;
31 import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Uninitialized;
32 import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_UninitializedThis;
33
34 /// From `stackMapTable.cpp`.
35 class VerificationTable {
36
37 private final int _code_length;
38 private final int _frame_count;
39 private final List<VerificationFrame> _frame_array;
40 private final VerifierImpl _verifier;
41
42 int get_frame_count() {
43 return _frame_count;
44 }
45
46 int get_offset(int index) {
47 return _frame_array.get(index).offset();
48 }
112 boolean match_stackmap(VerificationFrame frame, int target, int frame_index, boolean match, boolean update) {
113 if (frame_index < 0 || frame_index >= _frame_count) {
114 _verifier.verifyError(String.format("Expecting a stackmap frame at branch target %d", target));
115 }
116 VerificationFrame stackmap_frame = _frame_array.get(frame_index);
117 boolean result = true;
118 if (match) {
119 result = frame.is_assignable_to(stackmap_frame);
120 }
121 if (update) {
122 int lsize = stackmap_frame.locals_size();
123 int ssize = stackmap_frame.stack_size();
124 if (frame.locals_size() > lsize || frame.stack_size() > ssize) {
125 frame.reset();
126 }
127 frame.set_locals_size(lsize);
128 frame.copy_locals(stackmap_frame);
129 frame.set_stack_size(ssize);
130 frame.copy_stack(stackmap_frame);
131 frame.set_flags(stackmap_frame.flags());
132 }
133 return result;
134 }
135
136 void check_jump_target(VerificationFrame frame, int target) {
137 boolean match = match_stackmap(frame, target, true, false);
138 if (!match || (target < 0 || target >= _code_length)) {
139 _verifier.verifyError(String.format("Inconsistent stackmap frames at branch target %d", target));
140 }
141 }
142
143 static class StackMapReader {
144
145 private final VerificationWrapper.ConstantPoolWrapper _cp;
146 private final StackMapStream _stream;
147 private final byte[] _code_data;
148 private final int _code_length;
149 private final int _frame_count;
150 private int _parsed_frame_count;
151 private VerificationFrame _prev_frame;
152 char _max_locals, _max_stack;
153 boolean _first;
154
155 void check_verification_type_array_size(int size, int max_size) {
156 if (size < 0 || size > max_size) {
157 _verifier.classError("StackMapTable format error: bad type array size");
158 }
159 }
160
161 private static final int
162 SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247,
163 SAME_EXTENDED = 251,
164 FULL = 255;
165
166 public int get_frame_count() {
167 return _frame_count;
168 }
169
170 public VerificationFrame prev_frame() {
171 return _prev_frame;
172 }
173
174 public byte[] code_data() {
175 return _code_data;
176 }
177
178 public int code_length() {
179 return _code_length;
180 }
181
182 public boolean at_end() {
183 return _stream.at_end();
184 }
187 _parsed_frame_count++;
188 check_size();
189 VerificationFrame frame = next_helper();
190 if (frame != null) {
191 check_offset(frame);
192 _prev_frame = frame;
193 }
194 return frame;
195 }
196
197 public void check_end() {
198 if (_frame_count != _parsed_frame_count) {
199 _verifier.verifyError("wrong attribute size");
200 }
201 }
202
203 private final VerifierImpl _verifier;
204
205 public StackMapReader(byte[] stackmapData, byte[] code_data, int code_len,
206 VerificationFrame init_frame, char max_locals, char max_stack,
207 VerificationWrapper.ConstantPoolWrapper cp, VerifierImpl context) {
208 this._verifier = context;
209 _stream = new StackMapStream(stackmapData, _verifier);
210 _code_data = code_data;
211 _code_length = code_len;
212 _parsed_frame_count = 0;
213 _prev_frame = init_frame;
214 _max_locals = max_locals;
215 _max_stack = max_stack;
216 _first = true;
217 if (stackmapData != null) {
218 _cp = cp;
219 _frame_count = _stream.get_u2();
220 } else {
221 _cp = null;
222 _frame_count = 0;
223 }
224 }
225
226 void check_offset(VerificationFrame frame) {
227 int offset = frame.offset();
228 if (offset >= _code_length || _code_data[offset] == 0) {
229 _verifier.verifyError("StackMapTable error: bad offset");
230 }
231 }
232
233 void check_size() {
234 if (_frame_count < _parsed_frame_count) {
235 _verifier.verifyError("wrong attribute size");
268 flags[0] |= VerificationFrame.FLAG_THIS_UNINIT;
269 }
270 return VerificationType.uninitialized_this_type;
271 }
272 if (tag == ITEM_Uninitialized) {
273 int offset = _stream.get_u2();
274 if (offset >= _code_length || _code_data[offset] != VerifierImpl.NEW_OFFSET) {
275 _verifier.classError("StackMapTable format error: bad offset for Uninitialized");
276 }
277 return VerificationType.uninitialized_type(offset);
278 }
279 _verifier.classError("bad verification type");
280 return VerificationType.bogus_type;
281 }
282
283 VerificationFrame next_helper() {
284 VerificationFrame frame;
285 int offset;
286 VerificationType[] locals = null;
287 int frame_type = _stream.get_u1();
288 if (frame_type < 64) {
289 if (_first) {
290 offset = frame_type;
291 if (_prev_frame.locals_size() > 0) {
292 locals = new VerificationType[_prev_frame.locals_size()];
293 }
294 } else {
295 offset = _prev_frame.offset() + frame_type + 1;
296 locals = _prev_frame.locals();
297 }
298 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), 0, _max_locals, _max_stack, locals, null, _verifier);
299 if (_first && locals != null) {
300 frame.copy_locals(_prev_frame);
301 }
302 _first = false;
303 return frame;
304 }
305 if (frame_type < 128) {
306 if (_first) {
307 offset = frame_type - 64;
308 if (_prev_frame.locals_size() > 0) {
309 locals = new VerificationType[_prev_frame.locals_size()];
310 }
311 } else {
312 offset = _prev_frame.offset() + frame_type - 63;
313 locals = _prev_frame.locals();
314 }
315 VerificationType[] stack = new VerificationType[2];
316 int stack_size = 1;
317 stack[0] = parse_verification_type(null);
318 if (stack[0].is_category2()) {
319 stack[1] = stack[0].to_category2_2nd(_verifier);
320 stack_size = 2;
321 }
322 check_verification_type_array_size(stack_size, _max_stack);
323 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _verifier);
324 if (_first && locals != null) {
325 frame.copy_locals(_prev_frame);
326 }
327 _first = false;
328 return frame;
329 }
330 int offset_delta = _stream.get_u2();
331 if (frame_type < SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
332 _verifier.classError("reserved frame type");
333 }
334 if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
335 if (_first) {
336 offset = offset_delta;
337 if (_prev_frame.locals_size() > 0) {
338 locals = new VerificationType[_prev_frame.locals_size()];
339 }
340 } else {
341 offset = _prev_frame.offset() + offset_delta + 1;
342 locals = _prev_frame.locals();
343 }
344 VerificationType[] stack = new VerificationType[2];
345 int stack_size = 1;
346 stack[0] = parse_verification_type(null);
347 if (stack[0].is_category2()) {
348 stack[1] = stack[0].to_category2_2nd(_verifier);
349 stack_size = 2;
350 }
351 check_verification_type_array_size(stack_size, _max_stack);
352 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _verifier);
353 if (_first && locals != null) {
354 frame.copy_locals(_prev_frame);
355 }
356 _first = false;
357 return frame;
358 }
359 if (frame_type <= SAME_EXTENDED) {
360 locals = _prev_frame.locals();
361 int length = _prev_frame.locals_size();
362 int chops = SAME_EXTENDED - frame_type;
363 int new_length = length;
364 int flags = _prev_frame.flags();
365 if (chops != 0) {
366 new_length = chop(locals, length, chops);
367 check_verification_type_array_size(new_length, _max_locals);
368 flags = 0;
369 for (int i=0; i<new_length; i++) {
370 if (locals[i].is_uninitialized_this(_verifier)) {
371 flags |= VerificationFrame.FLAG_THIS_UNINIT;
372 break;
373 }
374 }
375 }
376 if (_first) {
377 offset = offset_delta;
378 if (new_length > 0) {
379 locals = new VerificationType[new_length];
380 } else {
381 locals = null;
382 }
383 } else {
384 offset = _prev_frame.offset() + offset_delta + 1;
385 }
386 frame = new VerificationFrame(offset, flags, new_length, 0, _max_locals, _max_stack, locals, null, _verifier);
387 if (_first && locals != null) {
388 frame.copy_locals(_prev_frame);
389 }
390 _first = false;
391 return frame;
392 } else if (frame_type < SAME_EXTENDED + 4) {
393 int appends = frame_type - SAME_EXTENDED;
394 int real_length = _prev_frame.locals_size();
395 int new_length = real_length + appends*2;
396 locals = new VerificationType[new_length];
397 VerificationType[] pre_locals = _prev_frame.locals();
398 int i;
399 for (i=0; i< _prev_frame.locals_size(); i++) {
400 locals[i] = pre_locals[i];
401 }
402 int[] flags = new int[]{_prev_frame.flags()};
403 for (i=0; i<appends; i++) {
404 locals[real_length] = parse_verification_type(flags);
405 if (locals[real_length].is_category2()) {
406 locals[real_length + 1] = locals[real_length].to_category2_2nd(_verifier);
407 ++real_length;
408 }
409 ++real_length;
410 }
411 check_verification_type_array_size(real_length, _max_locals);
412 if (_first) {
413 offset = offset_delta;
414 } else {
415 offset = _prev_frame.offset() + offset_delta + 1;
416 }
417 frame = new VerificationFrame(offset, flags[0], real_length, 0, _max_locals, _max_stack, locals, null, _verifier);
418 _first = false;
419 return frame;
420 }
421 if (frame_type == FULL) {
422 int flags[] = new int[]{0};
423 int locals_size = _stream.get_u2();
424 int real_locals_size = 0;
425 if (locals_size > 0) {
426 locals = new VerificationType[locals_size*2];
427 }
428 int i;
429 for (i=0; i<locals_size; i++) {
430 locals[real_locals_size] = parse_verification_type(flags);
431 if (locals[real_locals_size].is_category2()) {
432 locals[real_locals_size + 1] =
433 locals[real_locals_size].to_category2_2nd(_verifier);
434 ++real_locals_size;
435 }
436 ++real_locals_size;
437 }
439 int stack_size = _stream.get_u2();
440 int real_stack_size = 0;
441 VerificationType[] stack = null;
442 if (stack_size > 0) {
443 stack = new VerificationType[stack_size*2];
444 }
445 for (i=0; i<stack_size; i++) {
446 stack[real_stack_size] = parse_verification_type(null);
447 if (stack[real_stack_size].is_category2()) {
448 stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(_verifier);
449 ++real_stack_size;
450 }
451 ++real_stack_size;
452 }
453 check_verification_type_array_size(real_stack_size, _max_stack);
454 if (_first) {
455 offset = offset_delta;
456 } else {
457 offset = _prev_frame.offset() + offset_delta + 1;
458 }
459 frame = new VerificationFrame(offset, flags[0], real_locals_size, real_stack_size, _max_locals, _max_stack, locals, stack, _verifier);
460 _first = false;
461 return frame;
462 }
463 _verifier.classError("reserved frame type");
464 return null;
465 }
466 }
467 }
|
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.classfile.impl.verifier;
26
27 import java.lang.classfile.constantpool.NameAndTypeEntry;
28 import java.util.ArrayList;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Set;
32
33 import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Object;
34 import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_Uninitialized;
35 import static jdk.internal.classfile.impl.verifier.VerificationType.ITEM_UninitializedThis;
36
37 /// From `stackMapTable.cpp`.
38 class VerificationTable {
39
40 private final int _code_length;
41 private final int _frame_count;
42 private final List<VerificationFrame> _frame_array;
43 private final VerifierImpl _verifier;
44
45 int get_frame_count() {
46 return _frame_count;
47 }
48
49 int get_offset(int index) {
50 return _frame_array.get(index).offset();
51 }
115 boolean match_stackmap(VerificationFrame frame, int target, int frame_index, boolean match, boolean update) {
116 if (frame_index < 0 || frame_index >= _frame_count) {
117 _verifier.verifyError(String.format("Expecting a stackmap frame at branch target %d", target));
118 }
119 VerificationFrame stackmap_frame = _frame_array.get(frame_index);
120 boolean result = true;
121 if (match) {
122 result = frame.is_assignable_to(stackmap_frame);
123 }
124 if (update) {
125 int lsize = stackmap_frame.locals_size();
126 int ssize = stackmap_frame.stack_size();
127 if (frame.locals_size() > lsize || frame.stack_size() > ssize) {
128 frame.reset();
129 }
130 frame.set_locals_size(lsize);
131 frame.copy_locals(stackmap_frame);
132 frame.set_stack_size(ssize);
133 frame.copy_stack(stackmap_frame);
134 frame.set_flags(stackmap_frame.flags());
135 frame.set_assert_unset_fields(stackmap_frame.assert_unset_fields());
136 }
137 return result;
138 }
139
140 void check_jump_target(VerificationFrame frame, int target) {
141 boolean match = match_stackmap(frame, target, true, false);
142 if (!match || (target < 0 || target >= _code_length)) {
143 _verifier.verifyError(String.format("Inconsistent stackmap frames at branch target %d", target));
144 }
145 }
146
147 static class StackMapReader {
148
149 private final VerificationWrapper.ConstantPoolWrapper _cp;
150 private final StackMapStream _stream;
151 private final byte[] _code_data;
152 private final int _code_length;
153 private final int _frame_count;
154 private int _parsed_frame_count;
155 private VerificationFrame _prev_frame;
156 char _max_locals, _max_stack;
157 final Set<NameAndTypeEntry> strictFields;
158 Set<NameAndTypeEntry> _assert_unset_fields_buffer;
159 boolean _first;
160
161 void check_verification_type_array_size(int size, int max_size) {
162 if (size < 0 || size > max_size) {
163 _verifier.classError("StackMapTable format error: bad type array size");
164 }
165 }
166
167 private static final int
168 EARLY_LARVAL = 246,
169 SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247,
170 SAME_EXTENDED = 251,
171 FULL = 255;
172 private static final int RESERVED_TAGS_UPPER_LIMIT = EARLY_LARVAL; // not inclusive
173
174 public int get_frame_count() {
175 return _frame_count;
176 }
177
178 public VerificationFrame prev_frame() {
179 return _prev_frame;
180 }
181
182 public byte[] code_data() {
183 return _code_data;
184 }
185
186 public int code_length() {
187 return _code_length;
188 }
189
190 public boolean at_end() {
191 return _stream.at_end();
192 }
195 _parsed_frame_count++;
196 check_size();
197 VerificationFrame frame = next_helper();
198 if (frame != null) {
199 check_offset(frame);
200 _prev_frame = frame;
201 }
202 return frame;
203 }
204
205 public void check_end() {
206 if (_frame_count != _parsed_frame_count) {
207 _verifier.verifyError("wrong attribute size");
208 }
209 }
210
211 private final VerifierImpl _verifier;
212
213 public StackMapReader(byte[] stackmapData, byte[] code_data, int code_len,
214 VerificationFrame init_frame, char max_locals, char max_stack,
215 Set<NameAndTypeEntry> initial_strict_fields,
216 VerificationWrapper.ConstantPoolWrapper cp, VerifierImpl context) {
217 this._verifier = context;
218 _stream = new StackMapStream(stackmapData, _verifier);
219 _code_data = code_data;
220 _code_length = code_len;
221 _parsed_frame_count = 0;
222 _prev_frame = init_frame;
223 _max_locals = max_locals;
224 _max_stack = max_stack;
225 strictFields = Set.copyOf(initial_strict_fields);
226 _assert_unset_fields_buffer = initial_strict_fields;
227 _first = true;
228 if (stackmapData != null) {
229 _cp = cp;
230 _frame_count = _stream.get_u2();
231 } else {
232 _cp = null;
233 _frame_count = 0;
234 }
235 }
236
237 void check_offset(VerificationFrame frame) {
238 int offset = frame.offset();
239 if (offset >= _code_length || _code_data[offset] == 0) {
240 _verifier.verifyError("StackMapTable error: bad offset");
241 }
242 }
243
244 void check_size() {
245 if (_frame_count < _parsed_frame_count) {
246 _verifier.verifyError("wrong attribute size");
279 flags[0] |= VerificationFrame.FLAG_THIS_UNINIT;
280 }
281 return VerificationType.uninitialized_this_type;
282 }
283 if (tag == ITEM_Uninitialized) {
284 int offset = _stream.get_u2();
285 if (offset >= _code_length || _code_data[offset] != VerifierImpl.NEW_OFFSET) {
286 _verifier.classError("StackMapTable format error: bad offset for Uninitialized");
287 }
288 return VerificationType.uninitialized_type(offset);
289 }
290 _verifier.classError("bad verification type");
291 return VerificationType.bogus_type;
292 }
293
294 VerificationFrame next_helper() {
295 VerificationFrame frame;
296 int offset;
297 VerificationType[] locals = null;
298 int frame_type = _stream.get_u1();
299 if (frame_type == EARLY_LARVAL) {
300 int num_unset_fields = _stream.get_u2();
301 Set<NameAndTypeEntry> new_fields = new HashSet<>();
302 for (int i = 0; i < num_unset_fields; i++) {
303 int index = _stream.get_u2();
304 if (!_cp.is_within_bounds(index) || _cp.tagAt(index) != VerifierImpl.JVM_CONSTANT_NameAndType) {
305 _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
306 "Invalid constant pool index in early larval frame: %d".formatted(index)));
307 }
308 var tmp = _cp.cp.entryByIndex(index, NameAndTypeEntry.class);
309 if (!strictFields.contains(tmp)) {
310 _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
311 "Strict fields not a subset of initial strict instance fields: %s".formatted(tmp)));
312 } else {
313 new_fields.add(tmp);
314 }
315 }
316 // Only modify strict instance fields the frame has uninitialized this
317 if (_prev_frame.flag_this_uninit()) {
318 _assert_unset_fields_buffer = _prev_frame.merge_unset_fields(new_fields);
319 } else if (!new_fields.isEmpty()) {
320 _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
321 "Cannot have uninitialized strict fields after class initialization"));
322 }
323 // Continue reading frame data
324 if (at_end()) {
325 _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
326 "Early larval frame must be followed by a base frame"));
327 }
328 frame_type = _stream.get_u1();
329 if (frame_type == EARLY_LARVAL) {
330 _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
331 "Early larval frame must be followed by a base frame"));
332 }
333 }
334 if (frame_type < 64) {
335 if (_first) {
336 offset = frame_type;
337 if (_prev_frame.locals_size() > 0) {
338 locals = new VerificationType[_prev_frame.locals_size()];
339 }
340 } else {
341 offset = _prev_frame.offset() + frame_type + 1;
342 locals = _prev_frame.locals();
343 }
344 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier);
345 if (_first && locals != null) {
346 frame.copy_locals(_prev_frame);
347 }
348 _first = false;
349 return frame;
350 }
351 if (frame_type < 128) {
352 if (_first) {
353 offset = frame_type - 64;
354 if (_prev_frame.locals_size() > 0) {
355 locals = new VerificationType[_prev_frame.locals_size()];
356 }
357 } else {
358 offset = _prev_frame.offset() + frame_type - 63;
359 locals = _prev_frame.locals();
360 }
361 VerificationType[] stack = new VerificationType[2];
362 int stack_size = 1;
363 stack[0] = parse_verification_type(null);
364 if (stack[0].is_category2()) {
365 stack[1] = stack[0].to_category2_2nd(_verifier);
366 stack_size = 2;
367 }
368 check_verification_type_array_size(stack_size, _max_stack);
369 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier);
370 if (_first && locals != null) {
371 frame.copy_locals(_prev_frame);
372 }
373 _first = false;
374 return frame;
375 }
376 int offset_delta = _stream.get_u2();
377 if (frame_type < RESERVED_TAGS_UPPER_LIMIT) {
378 _verifier.classError("reserved frame type");
379 }
380 if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
381 if (_first) {
382 offset = offset_delta;
383 if (_prev_frame.locals_size() > 0) {
384 locals = new VerificationType[_prev_frame.locals_size()];
385 }
386 } else {
387 offset = _prev_frame.offset() + offset_delta + 1;
388 locals = _prev_frame.locals();
389 }
390 VerificationType[] stack = new VerificationType[2];
391 int stack_size = 1;
392 stack[0] = parse_verification_type(null);
393 if (stack[0].is_category2()) {
394 stack[1] = stack[0].to_category2_2nd(_verifier);
395 stack_size = 2;
396 }
397 check_verification_type_array_size(stack_size, _max_stack);
398 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier);
399 if (_first && locals != null) {
400 frame.copy_locals(_prev_frame);
401 }
402 _first = false;
403 return frame;
404 }
405 if (frame_type <= SAME_EXTENDED) {
406 locals = _prev_frame.locals();
407 int length = _prev_frame.locals_size();
408 int chops = SAME_EXTENDED - frame_type;
409 int new_length = length;
410 int flags = _prev_frame.flags();
411 if (chops != 0) {
412 new_length = chop(locals, length, chops);
413 check_verification_type_array_size(new_length, _max_locals);
414 flags = 0;
415 for (int i=0; i<new_length; i++) {
416 if (locals[i].is_uninitialized_this(_verifier)) {
417 flags |= VerificationFrame.FLAG_THIS_UNINIT;
418 break;
419 }
420 }
421 }
422 if (_first) {
423 offset = offset_delta;
424 if (new_length > 0) {
425 locals = new VerificationType[new_length];
426 } else {
427 locals = null;
428 }
429 } else {
430 offset = _prev_frame.offset() + offset_delta + 1;
431 }
432 frame = new VerificationFrame(offset, flags, new_length, 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier);
433 if (_first && locals != null) {
434 frame.copy_locals(_prev_frame);
435 }
436 _first = false;
437 return frame;
438 } else if (frame_type < SAME_EXTENDED + 4) {
439 int appends = frame_type - SAME_EXTENDED;
440 int real_length = _prev_frame.locals_size();
441 int new_length = real_length + appends*2;
442 locals = new VerificationType[new_length];
443 VerificationType[] pre_locals = _prev_frame.locals();
444 int i;
445 for (i=0; i< _prev_frame.locals_size(); i++) {
446 locals[i] = pre_locals[i];
447 }
448 int[] flags = new int[]{_prev_frame.flags()};
449 for (i=0; i<appends; i++) {
450 locals[real_length] = parse_verification_type(flags);
451 if (locals[real_length].is_category2()) {
452 locals[real_length + 1] = locals[real_length].to_category2_2nd(_verifier);
453 ++real_length;
454 }
455 ++real_length;
456 }
457 check_verification_type_array_size(real_length, _max_locals);
458 if (_first) {
459 offset = offset_delta;
460 } else {
461 offset = _prev_frame.offset() + offset_delta + 1;
462 }
463 frame = new VerificationFrame(offset, flags[0], real_length, 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier);
464 _first = false;
465 return frame;
466 }
467 if (frame_type == FULL) {
468 int flags[] = new int[]{0};
469 int locals_size = _stream.get_u2();
470 int real_locals_size = 0;
471 if (locals_size > 0) {
472 locals = new VerificationType[locals_size*2];
473 }
474 int i;
475 for (i=0; i<locals_size; i++) {
476 locals[real_locals_size] = parse_verification_type(flags);
477 if (locals[real_locals_size].is_category2()) {
478 locals[real_locals_size + 1] =
479 locals[real_locals_size].to_category2_2nd(_verifier);
480 ++real_locals_size;
481 }
482 ++real_locals_size;
483 }
485 int stack_size = _stream.get_u2();
486 int real_stack_size = 0;
487 VerificationType[] stack = null;
488 if (stack_size > 0) {
489 stack = new VerificationType[stack_size*2];
490 }
491 for (i=0; i<stack_size; i++) {
492 stack[real_stack_size] = parse_verification_type(null);
493 if (stack[real_stack_size].is_category2()) {
494 stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(_verifier);
495 ++real_stack_size;
496 }
497 ++real_stack_size;
498 }
499 check_verification_type_array_size(real_stack_size, _max_stack);
500 if (_first) {
501 offset = offset_delta;
502 } else {
503 offset = _prev_frame.offset() + offset_delta + 1;
504 }
505 frame = new VerificationFrame(offset, flags[0], real_locals_size, real_stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier);
506 _first = false;
507 return frame;
508 }
509 _verifier.classError("reserved frame type");
510 return null;
511 }
512 }
513 }
|