1 /*
  2  * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  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     }
 52 
 53     static class StackMapStream {
 54 
 55         private final byte[] _data;
 56         private int _index;
 57         private final VerifierImpl _verifier;
 58 
 59         StackMapStream(byte[] ah, VerifierImpl context) {
 60             _data = ah;
 61             _index = 0;
 62             _verifier = context;
 63         }
 64 
 65         int get_u1() {
 66             if (_data == null || _index >= _data.length) {
 67                 _verifier.classError("access beyond the end of attribute");
 68             }
 69             return _data[_index++] & 0xff;
 70         }
 71 
 72         int get_u2() {
 73             int res = get_u1() << 8;
 74             return res | get_u1();
 75         }
 76 
 77         boolean at_end() {
 78             return (_data == null) || (_index == _data.length);
 79         }
 80     }
 81 
 82     VerificationTable(StackMapReader reader,
 83             VerificationWrapper.ConstantPoolWrapper cp, VerifierImpl v) {
 84         _verifier = v;
 85         _code_length = reader.code_length();
 86         int _frame_count = reader.get_frame_count();
 87         _frame_array = new ArrayList<>(_frame_count);
 88         if (_frame_count > 0) {
 89             while (!reader.at_end()) {
 90                 VerificationFrame frame = reader.next();
 91                 if (frame != null) {
 92                     _frame_array.add(frame);
 93                 }
 94             }
 95         }
 96         reader.check_end();
 97         this._frame_count = _frame_array.size();
 98     }
 99 
100     int get_index_from_offset(int offset) {
101         int i = 0;
102         for (; i < _frame_count; i++) {
103             if (_frame_array.get(i).offset() == offset) {
104                 return i;
105             }
106         }
107         return i;
108     }
109 
110     boolean match_stackmap(VerificationFrame frame, int target, boolean match, boolean update) {
111         int index = get_index_from_offset(target);
112         return match_stackmap(frame, target, index, match, update);
113     }
114 
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         }
193 
194         public VerificationFrame next() {
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");
247             }
248         }
249 
250         int chop(VerificationType[] locals, int length, int chops) {
251             if (locals == null) return -1;
252             int pos = length - 1;
253             for (int i=0; i<chops; i++) {
254                 if (locals[pos].is_category2_2nd()) {
255                     pos -= 2;
256                 } else {
257                     pos--;
258                 }
259                 if (pos<0 && i<(chops-1)) return -1;
260             }
261             return pos+1;
262         }
263 
264         VerificationType parse_verification_type(int[] flags) {
265             int tag = _stream.get_u1();
266             if (tag < ITEM_UninitializedThis) {
267                 return VerificationType.from_tag(tag, _verifier);
268             }
269             if (tag == ITEM_Object) {
270                 int class_index = _stream.get_u2();
271                 int nconstants = _cp.entryCount();
272                 if (class_index <= 0 || class_index >= nconstants || _cp.tagAt(class_index) != VerifierImpl.JVM_CONSTANT_Class) {
273                     _verifier.classError("bad class index");
274                 }
275                 return VerificationType.reference_type(_cp.classNameAt(class_index));
276             }
277             if (tag == ITEM_UninitializedThis) {
278                 if (flags != null) {
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                 }
484                 check_verification_type_array_size(real_locals_size, _max_locals);
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 }