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.util.Arrays;
 28 
 29 /// From `stackMapFrame.cpp`.
 30 class VerificationFrame {
 31 
 32     public static final int FLAG_THIS_UNINIT = 0x01;
 33 
 34     private int _offset;
 35     private int _locals_size, _stack_size;
 36     private int _stack_mark;
 37     private final int _max_locals, _max_stack;
 38     private int _flags;
 39     private final VerificationType[] _locals, _stack;
 40     private final VerifierImpl _verifier;
 41 
 42     public VerificationFrame(int offset, int flags, int locals_size, int stack_size, int max_locals, int max_stack, VerificationType[] locals, VerificationType[] stack, VerifierImpl v) {
 43         this._offset = offset;
 44         this._locals_size = locals_size;
 45         this._stack_size = stack_size;
 46         this._stack_mark = -1;
 47         this._max_locals = max_locals;
 48         this._max_stack = max_stack;
 49         this._flags = flags;
 50         this._locals = locals;
 51         this._stack = stack;
 52         this._verifier = v;
 53     }
 54 
 55     @Override
 56     public String toString() {
 57         return "frame @" + _offset + " with locals " + (_locals == null ? "[]" : Arrays.asList(_locals)) + " and stack " + (_stack == null ? "[]" : Arrays.asList(_stack));
 58     }
 59 
 60     void set_offset(int offset) {
 61         this._offset = offset;
 62     }
 63 
 64     void set_flags(int flags) {
 65         _flags = flags;
 66     }
 67 
 68     void set_locals_size(int locals_size) {
 69         _locals_size = locals_size;
 70     }
 71 
 72     void set_stack_size(int stack_size) {
 73         _stack_size = _stack_mark = stack_size;
 74     }
 75 
 76     int offset() {
 77         return _offset;
 78     }
 79 
 80     VerifierImpl verifier() {
 81         return _verifier;
 82     }
 83 
 84     int flags() {
 85         return _flags;
 86     }
 87 
 88     int locals_size() {
 89         return _locals_size;
 90     }
 91 
 92     VerificationType[] locals() {
 93         return _locals;
 94     }
 95 
 96     int stack_size() {
 97         return _stack_size;
 98     }
 99 
100     VerificationType[] stack() {
101         return _stack;
102     }
103 
104     int max_locals() {
105         return _max_locals;
106     }
107 
108     boolean flag_this_uninit() {
109         return (_flags & FLAG_THIS_UNINIT) == FLAG_THIS_UNINIT;
110     }
111 
112     void reset() {
113         for (int i = 0; i < _max_locals; i++) {
114             _locals[i] = VerificationType.bogus_type;
115         }
116         for (int i = 0; i < _max_stack; i++) {
117             _stack[i] = VerificationType.bogus_type;
118         }
119     }
120 
121     void set_mark() {
122         if (_stack_mark != -1) {
123             for (int i = _stack_mark - 1; i >= _stack_size; --i) {
124                 _stack[i] = VerificationType.bogus_type;
125             }
126             _stack_mark = _stack_size;
127         }
128     }
129 
130     void push_stack(VerificationType type) {
131         if (type.is_check()) _verifier.verifyError("Must be a real type");
132         if (_stack_size >= _max_stack) {
133             _verifier.verifyError("Operand stack overflow");
134         }
135         _stack[_stack_size++] = type;
136     }
137 
138     void push_stack_2(VerificationType type1, VerificationType type2) {
139         if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double");
140         if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2");
141         if (_stack_size >= _max_stack - 1) {
142             _verifier.verifyError("Operand stack overflow");
143         }
144         _stack[_stack_size++] = type1;
145         _stack[_stack_size++] = type2;
146     }
147 
148     VerificationType pop_stack() {
149         if (_stack_size <= 0) {
150             _verifier.verifyError("Operand stack underflow");
151         }
152         return _stack[--_stack_size];
153     }
154 
155     VerificationType pop_stack(VerificationType type) {
156         if (_stack_size != 0) {
157             VerificationType top = _stack[_stack_size - 1];
158             boolean subtype = type.is_assignable_from(top, verifier());
159             if (subtype) {
160                 --_stack_size;
161                 return top;
162             }
163         }
164         return pop_stack_ex(type);
165     }
166 
167     void pop_stack_2(VerificationType type1, VerificationType type2) {
168         if (!(type1.is_long2() || type1.is_double2())) _verifier.verifyError("must be long/double");
169         if (!(type2.is_long() || type2.is_double())) _verifier.verifyError("must be long/double_2");
170         if (_stack_size >= 2) {
171             VerificationType top1 = _stack[_stack_size - 1];
172             boolean subtype1 = type1.is_assignable_from(top1, verifier());
173             VerificationType top2 = _stack[_stack_size - 2];
174             boolean subtype2 = type2.is_assignable_from(top2, verifier());
175             if (subtype1 && subtype2) {
176                 _stack_size -= 2;
177                 return;
178             }
179         }
180         pop_stack_ex(type1);
181         pop_stack_ex(type2);
182     }
183 
184     VerificationFrame(int max_locals, int max_stack, VerifierImpl verifier) {
185         _offset = 0;
186         _locals_size = 0;
187         _stack_size = 0;
188         _stack_mark = 0;
189         _max_locals = max_locals;
190         _max_stack = max_stack;
191         _flags = 0;
192         _verifier = verifier;
193         _locals = new VerificationType[max_locals];
194         _stack = new VerificationType[max_stack];
195         for (int i = 0; i < max_locals; i++) {
196             _locals[i] = VerificationType.bogus_type;
197         }
198         for (int i = 0; i < max_stack; i++) {
199             _stack[i] = VerificationType.bogus_type;
200         }
201     }
202 
203     VerificationFrame frame_in_exception_handler(int flags) {
204         return new VerificationFrame(_offset, flags, _locals_size, 0,
205                 _max_locals, _max_stack, _locals, new VerificationType[1],
206                 _verifier);
207     }
208 
209     void initialize_object(VerificationType old_object, VerificationType new_object) {
210         int i;
211         for (i = 0; i < _max_locals; i++) {
212             if (_locals[i].equals(old_object)) {
213                 _locals[i] = new_object;
214             }
215         }
216         for (i = 0; i < _stack_size; i++) {
217             if (_stack[i].equals(old_object)) {
218                 _stack[i] = new_object;
219             }
220         }
221         if (old_object.is_uninitialized_this(_verifier)) {
222             _flags = 0;
223         }
224     }
225 
226     VerificationType  set_locals_from_arg(VerificationWrapper.MethodWrapper m, VerificationType thisKlass) {
227         var ss = new VerificationSignature(m.descriptor(), true, _verifier);
228         int init_local_num = 0;
229         if (!m.isStatic()) {
230             init_local_num++;
231             if (VerifierImpl.object_initializer_name.equals(m.name()) && !VerifierImpl.java_lang_Object.equals(thisKlass.name())) {
232                 _locals[0] = VerificationType.uninitialized_this_type;
233                 _flags |= FLAG_THIS_UNINIT;
234             } else {
235                 _locals[0] = thisKlass;
236             }
237         }
238         while (!ss.atReturnType()) {
239             init_local_num += _verifier.change_sig_to_verificationType(ss, _locals, init_local_num);
240             ss.next();
241         }
242         _locals_size = init_local_num;
243         switch (ss.type()) {
244             case T_OBJECT:
245             case T_ARRAY:
246             {
247                 String sig = ss.asSymbol();
248                 return VerificationType.reference_type(sig);
249             }
250             case T_INT:         return VerificationType.integer_type;
251             case T_BYTE:        return VerificationType.byte_type;
252             case T_CHAR:        return VerificationType.char_type;
253             case T_SHORT:     return VerificationType.short_type;
254             case T_BOOLEAN: return VerificationType.boolean_type;
255             case T_FLOAT:     return VerificationType.float_type;
256             case T_DOUBLE:    return VerificationType.double_type;
257             case T_LONG:        return VerificationType.long_type;
258             case T_VOID:        return VerificationType.bogus_type;
259             default:
260                 _verifier.verifyError("Should not reach here");
261                 return VerificationType.bogus_type;
262         }
263     }
264 
265     void copy_locals(VerificationFrame src) {
266         int len = src.locals_size() < _locals_size ? src.locals_size() : _locals_size;
267         if (len > 0) System.arraycopy(src.locals(), 0, _locals, 0, len);
268     }
269 
270     void copy_stack(VerificationFrame src) {
271         int len = src.stack_size() < _stack_size ? src.stack_size() : _stack_size;
272         if (len > 0) System.arraycopy(src.stack(), 0, _stack, 0, len);
273     }
274 
275     private int is_assignable_to(VerificationType[] from, VerificationType[] to, int len) {
276         int i = 0;
277         for (; i < len; i++) {
278             if (!to[i].is_assignable_from(from[i], verifier())) {
279                 break;
280             }
281         }
282         return i;
283     }
284 
285     boolean is_assignable_to(VerificationFrame target) {
286         if (_max_locals != target.max_locals()) {
287             _verifier.verifyError("Locals size mismatch", this, target);
288         }
289         if (_stack_size != target.stack_size()) {
290             _verifier.verifyError("Stack size mismatch", this, target);
291         }
292         int mismatch_loc;
293         mismatch_loc = is_assignable_to(_locals, target.locals(), target.locals_size());
294         if (mismatch_loc != target.locals_size()) {
295             _verifier.verifyError("Bad type", this, target);
296         }
297         mismatch_loc = is_assignable_to(_stack, target.stack(), _stack_size);
298         if (mismatch_loc != _stack_size) {
299             _verifier.verifyError("Bad type", this, target);
300         }
301 
302         if ((_flags | target.flags()) == target.flags()) {
303             return true;
304         } else {
305             _verifier.verifyError("Bad flags", this, target);
306         }
307         return false;
308     }
309 
310     VerificationType pop_stack_ex(VerificationType type) {
311         if (_stack_size <= 0) {
312             _verifier.verifyError("Operand stack underflow");
313         }
314         VerificationType top = _stack[--_stack_size];
315         boolean subtype = type.is_assignable_from(top, verifier());
316         if (!subtype) {
317             _verifier.verifyError("Bad type on operand stack");
318         }
319         return top;
320     }
321 
322     VerificationType get_local(int index, VerificationType type) {
323         if (index >= _max_locals) {
324             _verifier.verifyError("Local variable table overflow");
325         }
326         boolean subtype = type.is_assignable_from(_locals[index],
327             verifier());
328         if (!subtype) {
329             _verifier.verifyError("Bad local variable type");
330         }
331         if(index >= _locals_size) { _locals_size = index + 1; }
332         return _locals[index];
333     }
334 
335     void get_local_2(int index, VerificationType type1, VerificationType type2) {
336         if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double");
337         if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2");
338         if (index >= _locals_size - 1) {
339             _verifier.verifyError("get long/double overflows locals");
340         }
341         boolean subtype = type1.is_assignable_from(_locals[index], verifier());
342         if (!subtype) {
343             _verifier.verifyError("Bad local variable type");
344         } else {
345             subtype = type2.is_assignable_from(_locals[index + 1], verifier());
346             if (!subtype) {
347                 _verifier.verifyError("Bad local variable type");
348             }
349         }
350     }
351 
352     void set_local(int index, VerificationType type) {
353         if (type.is_check()) _verifier.verifyError("Must be a real type");
354         if (index >= _max_locals) {
355             _verifier.verifyError("Local variable table overflow");
356         }
357         if (_locals[index].is_double() || _locals[index].is_long()) {
358             if ((index + 1) >= _locals_size) _verifier.verifyError("Local variable table overflow");
359             _locals[index + 1] = VerificationType.bogus_type;
360         }
361         if (_locals[index].is_double2() || _locals[index].is_long2()) {
362             if (index < 1) _verifier.verifyError("Local variable table underflow");
363             _locals[index - 1] = VerificationType.bogus_type;
364         }
365         _locals[index] = type;
366         if (index >= _locals_size) {
367             for (int i=_locals_size; i<index; i++) {
368                 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type");
369             }
370             _locals_size = index + 1;
371         }
372     }
373 
374     void set_local_2(int index, VerificationType type1, VerificationType type2) {
375         if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double");
376         if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2");
377         if (index >= _max_locals - 1) {
378             _verifier.verifyError("Local variable table overflow");
379         }
380         if (_locals[index+1].is_double() || _locals[index+1].is_long()) {
381             if ((index + 2) >= _locals_size) _verifier.verifyError("Local variable table overflow");
382             _locals[index + 2] = VerificationType.bogus_type;
383         }
384         if (_locals[index].is_double2() || _locals[index].is_long2()) {
385             if (index < 1) _verifier.verifyError("Local variable table underflow");
386             _locals[index - 1] = VerificationType.bogus_type;
387         }
388         _locals[index] = type1;
389         _locals[index+1] = type2;
390         if (index >= _locals_size - 1) {
391             for (int i=_locals_size; i<index; i++) {
392                 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type");
393             }
394             _locals_size = index + 2;
395         }
396     }
397 }