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 }