< prev index next >

src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java

Print this page

  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.StackMapGenerator.*;
 31 
 32 /// From `stackMapTable.cpp`.
 33 class VerificationTable {
 34 
 35     private final int _code_length;
 36     private final int _frame_count;
 37     private final List<VerificationFrame> _frame_array;
 38     private final VerifierImpl _verifier;
 39 
 40     int get_frame_count() {
 41         return _frame_count;
 42     }
 43 
 44     int get_offset(int index) {
 45         return _frame_array.get(index).offset();
 46     }
 47 
 48     static class StackMapStream {

110     boolean match_stackmap(VerificationFrame frame, int target, int frame_index, boolean match, boolean update) {
111         if (frame_index < 0 || frame_index >= _frame_count) {
112             _verifier.verifyError(String.format("Expecting a stackmap frame at branch target %d", target));
113         }
114         VerificationFrame stackmap_frame = _frame_array.get(frame_index);
115         boolean result = true;
116         if (match) {
117             result = frame.is_assignable_to(stackmap_frame);
118         }
119         if (update) {
120             int lsize = stackmap_frame.locals_size();
121             int ssize = stackmap_frame.stack_size();
122             if (frame.locals_size() > lsize || frame.stack_size() > ssize) {
123                 frame.reset();
124             }
125             frame.set_locals_size(lsize);
126             frame.copy_locals(stackmap_frame);
127             frame.set_stack_size(ssize);
128             frame.copy_stack(stackmap_frame);
129             frame.set_flags(stackmap_frame.flags());

130         }
131         return result;
132     }
133 
134     void check_jump_target(VerificationFrame frame, int target) {
135         boolean match = match_stackmap(frame, target, true, false);
136         if (!match || (target < 0 || target >= _code_length)) {
137             _verifier.verifyError(String.format("Inconsistent stackmap frames at branch target %d", target));
138         }
139     }
140 
141     static class StackMapReader {
142 
143         private final VerificationWrapper.ConstantPoolWrapper _cp;
144         private final StackMapStream _stream;
145         private final byte[] _code_data;
146         private final int _code_length;
147         private final int _frame_count;
148         private int _parsed_frame_count;
149         private VerificationFrame _prev_frame;
150         char _max_locals, _max_stack;


151         boolean _first;
152 
153         void check_verification_type_array_size(int size, int max_size) {
154             if (size < 0 || size > max_size) {
155                 _verifier.classError("StackMapTable format error: bad type array size");
156             }
157         }
158 
159         public int get_frame_count() {
160             return _frame_count;
161         }
162 
163         public VerificationFrame prev_frame() {
164             return _prev_frame;
165         }
166 
167         public byte[] code_data() {
168             return _code_data;
169         }
170 

180             _parsed_frame_count++;
181             check_size();
182             VerificationFrame frame = next_helper();
183             if (frame != null) {
184                 check_offset(frame);
185                 _prev_frame = frame;
186             }
187             return frame;
188         }
189 
190         public void check_end() {
191             if (_frame_count != _parsed_frame_count) {
192                 _verifier.verifyError("wrong attribute size");
193             }
194         }
195 
196         private final VerifierImpl _verifier;
197 
198         public StackMapReader(byte[] stackmapData, byte[] code_data, int code_len,
199                               VerificationFrame init_frame, char max_locals, char max_stack,

200                               VerificationWrapper.ConstantPoolWrapper cp, VerifierImpl context) {
201             this._verifier = context;
202             _stream = new StackMapStream(stackmapData, _verifier);
203             _code_data = code_data;
204             _code_length = code_len;
205             _parsed_frame_count = 0;
206             _prev_frame = init_frame;
207             _max_locals = max_locals;
208             _max_stack = max_stack;


209             _first = true;
210             if (stackmapData != null) {
211                 _cp = cp;
212                 _frame_count = _stream.get_u2();
213             } else {
214                 _cp = null;
215                 _frame_count = 0;
216             }
217         }
218 
219         void check_offset(VerificationFrame frame) {
220             int offset = frame.offset();
221             if (offset >= _code_length || _code_data[offset] == 0) {
222                 _verifier.verifyError("StackMapTable error: bad offset");
223             }
224         }
225 
226         void check_size() {
227             if (_frame_count < _parsed_frame_count) {
228                 _verifier.verifyError("wrong attribute size");

261                     flags[0] |= VerificationFrame.FLAG_THIS_UNINIT;
262                 }
263                 return VerificationType.uninitialized_this_type;
264             }
265             if (tag == ITEM_UNINITIALIZED) {
266                 int offset = _stream.get_u2();
267                 if (offset >= _code_length || _code_data[offset] != VerifierImpl.NEW_OFFSET) {
268                     _verifier.classError("StackMapTable format error: bad offset for Uninitialized");
269                 }
270                 return VerificationType.uninitialized_type(offset);
271             }
272             _verifier.classError("bad verification type");
273             return VerificationType.bogus_type;
274         }
275 
276         VerificationFrame next_helper() {
277             VerificationFrame frame;
278             int offset;
279             VerificationType[] locals = null;
280             int frame_type = _stream.get_u1();



































281             if (frame_type <= SAME_FRAME_END) {
282                 if (_first) {
283                     offset = frame_type;
284                     if (_prev_frame.locals_size() > 0) {
285                         locals = new VerificationType[_prev_frame.locals_size()];
286                     }
287                 } else {
288                     offset = _prev_frame.offset() + frame_type + 1;
289                     locals = _prev_frame.locals();
290                 }
291                 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), 0, _max_locals, _max_stack, locals, null, _verifier);
292                 if (_first && locals != null) {
293                     frame.copy_locals(_prev_frame);
294                 }
295                 _first = false;
296                 return frame;
297             }
298             if (frame_type <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) {
299                 if (_first) {
300                     offset = frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_START;
301                     if (_prev_frame.locals_size() > 0) {
302                         locals = new VerificationType[_prev_frame.locals_size()];
303                     }
304                 } else {
305                     offset = _prev_frame.offset() + frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_START + 1;
306                     locals = _prev_frame.locals();
307                 }
308                 VerificationType[] stack = new VerificationType[2];
309                 int stack_size = 1;
310                 stack[0] = parse_verification_type(null);
311                 if (stack[0].is_category2()) {
312                     stack[1] = stack[0].to_category2_2nd(_verifier);
313                     stack_size = 2;
314                 }
315                 check_verification_type_array_size(stack_size, _max_stack);
316                 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _verifier);
317                 if (_first && locals != null) {
318                     frame.copy_locals(_prev_frame);
319                 }
320                 _first = false;
321                 return frame;
322             }
323             int offset_delta = _stream.get_u2();
324             if (frame_type < SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
325                 _verifier.classError("reserved frame type");
326             }
327             if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
328                 if (_first) {
329                     offset = offset_delta;
330                     if (_prev_frame.locals_size() > 0) {
331                         locals = new VerificationType[_prev_frame.locals_size()];
332                     }
333                 } else {
334                     offset = _prev_frame.offset() + offset_delta + 1;
335                     locals = _prev_frame.locals();
336                 }
337                 VerificationType[] stack = new VerificationType[2];
338                 int stack_size = 1;
339                 stack[0] = parse_verification_type(null);
340                 if (stack[0].is_category2()) {
341                     stack[1] = stack[0].to_category2_2nd(_verifier);
342                     stack_size = 2;
343                 }
344                 check_verification_type_array_size(stack_size, _max_stack);
345                 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _verifier);
346                 if (_first && locals != null) {
347                     frame.copy_locals(_prev_frame);
348                 }
349                 _first = false;
350                 return frame;
351             }
352             if (frame_type <= SAME_FRAME_EXTENDED) {
353                 locals = _prev_frame.locals();
354                 int length = _prev_frame.locals_size();
355                 int chops = SAME_FRAME_EXTENDED - frame_type;
356                 int new_length = length;
357                 int flags = _prev_frame.flags();
358                 if (chops != 0) {
359                     new_length = chop(locals, length, chops);
360                     check_verification_type_array_size(new_length, _max_locals);
361                     flags = 0;
362                     for (int i=0; i<new_length; i++) {
363                         if (locals[i].is_uninitialized_this(_verifier)) {
364                             flags |= VerificationFrame.FLAG_THIS_UNINIT;
365                             break;
366                         }
367                     }
368                 }
369                 if (_first) {
370                     offset = offset_delta;
371                     if (new_length > 0) {
372                         locals = new VerificationType[new_length];
373                     } else {
374                         locals = null;
375                     }
376                 } else {
377                     offset = _prev_frame.offset() + offset_delta + 1;
378                 }
379                 frame = new VerificationFrame(offset, flags, new_length, 0, _max_locals, _max_stack, locals, null, _verifier);
380                 if (_first && locals != null) {
381                     frame.copy_locals(_prev_frame);
382                 }
383                 _first = false;
384                 return frame;
385             } else if (frame_type <= APPEND_FRAME_END) {
386                 int appends = frame_type - APPEND_FRAME_START + 1;
387                 int real_length = _prev_frame.locals_size();
388                 int new_length = real_length + appends*2;
389                 locals = new VerificationType[new_length];
390                 VerificationType[] pre_locals = _prev_frame.locals();
391                 int i;
392                 for (i=0; i< _prev_frame.locals_size(); i++) {
393                     locals[i] = pre_locals[i];
394                 }
395                 int[] flags = new int[]{_prev_frame.flags()};
396                 for (i=0; i<appends; i++) {
397                     locals[real_length] = parse_verification_type(flags);
398                     if (locals[real_length].is_category2()) {
399                         locals[real_length + 1] = locals[real_length].to_category2_2nd(_verifier);
400                         ++real_length;
401                     }
402                     ++real_length;
403                 }
404                 check_verification_type_array_size(real_length, _max_locals);
405                 if (_first) {
406                     offset = offset_delta;
407                 } else {
408                     offset = _prev_frame.offset() + offset_delta + 1;
409                 }
410                 frame = new VerificationFrame(offset, flags[0], real_length, 0, _max_locals, _max_stack, locals, null, _verifier);
411                 _first = false;
412                 return frame;
413             }
414             if (frame_type == FULL_FRAME) {
415                 int flags[] = new int[]{0};
416                 int locals_size = _stream.get_u2();
417                 int real_locals_size = 0;
418                 if (locals_size > 0) {
419                     locals = new VerificationType[locals_size*2];
420                 }
421                 int i;
422                 for (i=0; i<locals_size; i++) {
423                     locals[real_locals_size] = parse_verification_type(flags);
424                     if (locals[real_locals_size].is_category2()) {
425                         locals[real_locals_size + 1] =
426                                 locals[real_locals_size].to_category2_2nd(_verifier);
427                         ++real_locals_size;
428                     }
429                     ++real_locals_size;
430                 }

432                 int stack_size = _stream.get_u2();
433                 int real_stack_size = 0;
434                 VerificationType[] stack = null;
435                 if (stack_size > 0) {
436                     stack = new VerificationType[stack_size*2];
437                 }
438                 for (i=0; i<stack_size; i++) {
439                     stack[real_stack_size] = parse_verification_type(null);
440                     if (stack[real_stack_size].is_category2()) {
441                         stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(_verifier);
442                         ++real_stack_size;
443                     }
444                     ++real_stack_size;
445                 }
446                 check_verification_type_array_size(real_stack_size, _max_stack);
447                 if (_first) {
448                     offset = offset_delta;
449                 } else {
450                     offset = _prev_frame.offset() + offset_delta + 1;
451                 }
452                 frame = new VerificationFrame(offset, flags[0], real_locals_size, real_stack_size, _max_locals, _max_stack, locals, stack, _verifier);
453                 _first = false;
454                 return frame;
455             }
456             _verifier.classError("reserved frame type");
457             return null;
458         }
459     }
460 }

  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.StackMapGenerator.*;
 34 
 35 /// From `stackMapTable.cpp`.
 36 class VerificationTable {
 37 
 38     private final int _code_length;
 39     private final int _frame_count;
 40     private final List<VerificationFrame> _frame_array;
 41     private final VerifierImpl _verifier;
 42 
 43     int get_frame_count() {
 44         return _frame_count;
 45     }
 46 
 47     int get_offset(int index) {
 48         return _frame_array.get(index).offset();
 49     }
 50 
 51     static class StackMapStream {

113     boolean match_stackmap(VerificationFrame frame, int target, int frame_index, boolean match, boolean update) {
114         if (frame_index < 0 || frame_index >= _frame_count) {
115             _verifier.verifyError(String.format("Expecting a stackmap frame at branch target %d", target));
116         }
117         VerificationFrame stackmap_frame = _frame_array.get(frame_index);
118         boolean result = true;
119         if (match) {
120             result = frame.is_assignable_to(stackmap_frame);
121         }
122         if (update) {
123             int lsize = stackmap_frame.locals_size();
124             int ssize = stackmap_frame.stack_size();
125             if (frame.locals_size() > lsize || frame.stack_size() > ssize) {
126                 frame.reset();
127             }
128             frame.set_locals_size(lsize);
129             frame.copy_locals(stackmap_frame);
130             frame.set_stack_size(ssize);
131             frame.copy_stack(stackmap_frame);
132             frame.set_flags(stackmap_frame.flags());
133             frame.set_assert_unset_fields(stackmap_frame.assert_unset_fields());
134         }
135         return result;
136     }
137 
138     void check_jump_target(VerificationFrame frame, int target) {
139         boolean match = match_stackmap(frame, target, true, false);
140         if (!match || (target < 0 || target >= _code_length)) {
141             _verifier.verifyError(String.format("Inconsistent stackmap frames at branch target %d", target));
142         }
143     }
144 
145     static class StackMapReader {
146 
147         private final VerificationWrapper.ConstantPoolWrapper _cp;
148         private final StackMapStream _stream;
149         private final byte[] _code_data;
150         private final int _code_length;
151         private final int _frame_count;
152         private int _parsed_frame_count;
153         private VerificationFrame _prev_frame;
154         char _max_locals, _max_stack;
155         final Set<NameAndTypeEntry> strictFields;
156         Set<NameAndTypeEntry> _assert_unset_fields_buffer;
157         boolean _first;
158 
159         void check_verification_type_array_size(int size, int max_size) {
160             if (size < 0 || size > max_size) {
161                 _verifier.classError("StackMapTable format error: bad type array size");
162             }
163         }
164 
165         public int get_frame_count() {
166             return _frame_count;
167         }
168 
169         public VerificationFrame prev_frame() {
170             return _prev_frame;
171         }
172 
173         public byte[] code_data() {
174             return _code_data;
175         }
176 

186             _parsed_frame_count++;
187             check_size();
188             VerificationFrame frame = next_helper();
189             if (frame != null) {
190                 check_offset(frame);
191                 _prev_frame = frame;
192             }
193             return frame;
194         }
195 
196         public void check_end() {
197             if (_frame_count != _parsed_frame_count) {
198                 _verifier.verifyError("wrong attribute size");
199             }
200         }
201 
202         private final VerifierImpl _verifier;
203 
204         public StackMapReader(byte[] stackmapData, byte[] code_data, int code_len,
205                               VerificationFrame init_frame, char max_locals, char max_stack,
206                               Set<NameAndTypeEntry> initial_strict_fields,
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             strictFields = Set.copyOf(initial_strict_fields);
217             _assert_unset_fields_buffer = initial_strict_fields;
218             _first = true;
219             if (stackmapData != null) {
220                 _cp = cp;
221                 _frame_count = _stream.get_u2();
222             } else {
223                 _cp = null;
224                 _frame_count = 0;
225             }
226         }
227 
228         void check_offset(VerificationFrame frame) {
229             int offset = frame.offset();
230             if (offset >= _code_length || _code_data[offset] == 0) {
231                 _verifier.verifyError("StackMapTable error: bad offset");
232             }
233         }
234 
235         void check_size() {
236             if (_frame_count < _parsed_frame_count) {
237                 _verifier.verifyError("wrong attribute size");

270                     flags[0] |= VerificationFrame.FLAG_THIS_UNINIT;
271                 }
272                 return VerificationType.uninitialized_this_type;
273             }
274             if (tag == ITEM_UNINITIALIZED) {
275                 int offset = _stream.get_u2();
276                 if (offset >= _code_length || _code_data[offset] != VerifierImpl.NEW_OFFSET) {
277                     _verifier.classError("StackMapTable format error: bad offset for Uninitialized");
278                 }
279                 return VerificationType.uninitialized_type(offset);
280             }
281             _verifier.classError("bad verification type");
282             return VerificationType.bogus_type;
283         }
284 
285         VerificationFrame next_helper() {
286             VerificationFrame frame;
287             int offset;
288             VerificationType[] locals = null;
289             int frame_type = _stream.get_u1();
290             if (frame_type == EARLY_LARVAL) {
291                 int num_unset_fields = _stream.get_u2();
292                 Set<NameAndTypeEntry> new_fields = new HashSet<>();
293                 for (int i = 0; i < num_unset_fields; i++) {
294                     int index = _stream.get_u2();
295                     if (!_cp.is_within_bounds(index) || _cp.tagAt(index) != VerifierImpl.JVM_CONSTANT_NameAndType) {
296                         _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
297                                 "Invalid constant pool index in early larval frame: %d".formatted(index)));
298                     }
299                     var tmp = _cp.cp.entryByIndex(index, NameAndTypeEntry.class);
300                     if (!strictFields.contains(tmp)) {
301                         _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
302                                 "Strict fields not a subset of initial strict instance fields: %s".formatted(tmp)));
303                     } else {
304                         new_fields.add(tmp);
305                     }
306                 }
307                 // Only modify strict instance fields the frame has uninitialized this
308                 if (_prev_frame.flag_this_uninit()) {
309                     _assert_unset_fields_buffer = _prev_frame.merge_unset_fields(new_fields);
310                 } else if (!new_fields.isEmpty()) {
311                     _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
312                             "Cannot have uninitialized strict fields after class initialization"));
313                 }
314                 // Continue reading frame data
315                 if (at_end()) {
316                     _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
317                             "Early larval frame must be followed by a base frame"));
318                 }
319                 frame_type = _stream.get_u1();
320                 if (frame_type == EARLY_LARVAL) {
321                     _prev_frame.verifier().verifyError("Invalid use of strict instance fields %d %s %s".formatted(_prev_frame.offset(), _prev_frame,
322                             "Early larval frame must be followed by a base frame"));
323                 }
324             }
325             if (frame_type <= SAME_FRAME_END) {
326                 if (_first) {
327                     offset = frame_type;
328                     if (_prev_frame.locals_size() > 0) {
329                         locals = new VerificationType[_prev_frame.locals_size()];
330                     }
331                 } else {
332                     offset = _prev_frame.offset() + frame_type + 1;
333                     locals = _prev_frame.locals();
334                 }
335                 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier);
336                 if (_first && locals != null) {
337                     frame.copy_locals(_prev_frame);
338                 }
339                 _first = false;
340                 return frame;
341             }
342             if (frame_type <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) {
343                 if (_first) {
344                     offset = frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_START;
345                     if (_prev_frame.locals_size() > 0) {
346                         locals = new VerificationType[_prev_frame.locals_size()];
347                     }
348                 } else {
349                     offset = _prev_frame.offset() + frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_START + 1;
350                     locals = _prev_frame.locals();
351                 }
352                 VerificationType[] stack = new VerificationType[2];
353                 int stack_size = 1;
354                 stack[0] = parse_verification_type(null);
355                 if (stack[0].is_category2()) {
356                     stack[1] = stack[0].to_category2_2nd(_verifier);
357                     stack_size = 2;
358                 }
359                 check_verification_type_array_size(stack_size, _max_stack);
360                 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier);
361                 if (_first && locals != null) {
362                     frame.copy_locals(_prev_frame);
363                 }
364                 _first = false;
365                 return frame;
366             }
367             int offset_delta = _stream.get_u2();
368             if (frame_type <= RESERVED_END) {
369                 _verifier.classError("reserved frame type");
370             }
371             if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
372                 if (_first) {
373                     offset = offset_delta;
374                     if (_prev_frame.locals_size() > 0) {
375                         locals = new VerificationType[_prev_frame.locals_size()];
376                     }
377                 } else {
378                     offset = _prev_frame.offset() + offset_delta + 1;
379                     locals = _prev_frame.locals();
380                 }
381                 VerificationType[] stack = new VerificationType[2];
382                 int stack_size = 1;
383                 stack[0] = parse_verification_type(null);
384                 if (stack[0].is_category2()) {
385                     stack[1] = stack[0].to_category2_2nd(_verifier);
386                     stack_size = 2;
387                 }
388                 check_verification_type_array_size(stack_size, _max_stack);
389                 frame = new VerificationFrame(offset, _prev_frame.flags(), _prev_frame.locals_size(), stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier);
390                 if (_first && locals != null) {
391                     frame.copy_locals(_prev_frame);
392                 }
393                 _first = false;
394                 return frame;
395             }
396             if (frame_type <= SAME_FRAME_EXTENDED) {
397                 locals = _prev_frame.locals();
398                 int length = _prev_frame.locals_size();
399                 int chops = SAME_FRAME_EXTENDED - frame_type;
400                 int new_length = length;
401                 int flags = _prev_frame.flags();
402                 if (chops != 0) {
403                     new_length = chop(locals, length, chops);
404                     check_verification_type_array_size(new_length, _max_locals);
405                     flags = 0;
406                     for (int i=0; i<new_length; i++) {
407                         if (locals[i].is_uninitialized_this(_verifier)) {
408                             flags |= VerificationFrame.FLAG_THIS_UNINIT;
409                             break;
410                         }
411                     }
412                 }
413                 if (_first) {
414                     offset = offset_delta;
415                     if (new_length > 0) {
416                         locals = new VerificationType[new_length];
417                     } else {
418                         locals = null;
419                     }
420                 } else {
421                     offset = _prev_frame.offset() + offset_delta + 1;
422                 }
423                 frame = new VerificationFrame(offset, flags, new_length, 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier);
424                 if (_first && locals != null) {
425                     frame.copy_locals(_prev_frame);
426                 }
427                 _first = false;
428                 return frame;
429             } else if (frame_type <= APPEND_FRAME_END) {
430                 int appends = frame_type - APPEND_FRAME_START + 1;
431                 int real_length = _prev_frame.locals_size();
432                 int new_length = real_length + appends*2;
433                 locals = new VerificationType[new_length];
434                 VerificationType[] pre_locals = _prev_frame.locals();
435                 int i;
436                 for (i=0; i< _prev_frame.locals_size(); i++) {
437                     locals[i] = pre_locals[i];
438                 }
439                 int[] flags = new int[]{_prev_frame.flags()};
440                 for (i=0; i<appends; i++) {
441                     locals[real_length] = parse_verification_type(flags);
442                     if (locals[real_length].is_category2()) {
443                         locals[real_length + 1] = locals[real_length].to_category2_2nd(_verifier);
444                         ++real_length;
445                     }
446                     ++real_length;
447                 }
448                 check_verification_type_array_size(real_length, _max_locals);
449                 if (_first) {
450                     offset = offset_delta;
451                 } else {
452                     offset = _prev_frame.offset() + offset_delta + 1;
453                 }
454                 frame = new VerificationFrame(offset, flags[0], real_length, 0, _max_locals, _max_stack, locals, null, _assert_unset_fields_buffer, _verifier);
455                 _first = false;
456                 return frame;
457             }
458             if (frame_type == FULL_FRAME) {
459                 int flags[] = new int[]{0};
460                 int locals_size = _stream.get_u2();
461                 int real_locals_size = 0;
462                 if (locals_size > 0) {
463                     locals = new VerificationType[locals_size*2];
464                 }
465                 int i;
466                 for (i=0; i<locals_size; i++) {
467                     locals[real_locals_size] = parse_verification_type(flags);
468                     if (locals[real_locals_size].is_category2()) {
469                         locals[real_locals_size + 1] =
470                                 locals[real_locals_size].to_category2_2nd(_verifier);
471                         ++real_locals_size;
472                     }
473                     ++real_locals_size;
474                 }

476                 int stack_size = _stream.get_u2();
477                 int real_stack_size = 0;
478                 VerificationType[] stack = null;
479                 if (stack_size > 0) {
480                     stack = new VerificationType[stack_size*2];
481                 }
482                 for (i=0; i<stack_size; i++) {
483                     stack[real_stack_size] = parse_verification_type(null);
484                     if (stack[real_stack_size].is_category2()) {
485                         stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(_verifier);
486                         ++real_stack_size;
487                     }
488                     ++real_stack_size;
489                 }
490                 check_verification_type_array_size(real_stack_size, _max_stack);
491                 if (_first) {
492                     offset = offset_delta;
493                 } else {
494                     offset = _prev_frame.offset() + offset_delta + 1;
495                 }
496                 frame = new VerificationFrame(offset, flags[0], real_locals_size, real_stack_size, _max_locals, _max_stack, locals, stack, _assert_unset_fields_buffer, _verifier);
497                 _first = false;
498                 return frame;
499             }
500             _verifier.classError("reserved frame type");
501             return null;
502         }
503     }
504 }
< prev index next >