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.lang.classfile.constantpool.Utf8Entry;
29 import java.util.Arrays;
30 import java.util.Set;
31
32 import jdk.internal.classfile.impl.TemporaryConstantPool;
33
34 /// From `stackMapFrame.cpp`.
35 class VerificationFrame {
36
37 public static final int FLAG_THIS_UNINIT = 0x01;
38
39 private int _offset;
40 private int _locals_size, _stack_size;
41 private int _stack_mark;
42 private final int _max_locals, _max_stack;
43 private int _flags;
44 private final VerificationType[] _locals, _stack;
45 private Set<NameAndTypeEntry> _assert_unset_fields;
46 private final VerifierImpl _verifier;
47
48 public VerificationFrame(int offset, int flags, int locals_size, int stack_size, int max_locals, int max_stack,
49 VerificationType[] locals, VerificationType[] stack, Set<NameAndTypeEntry> assert_unset_fields, VerifierImpl v) {
50 this._offset = offset;
51 this._locals_size = locals_size;
52 this._stack_size = stack_size;
53 this._stack_mark = -1;
54 this._max_locals = max_locals;
55 this._max_stack = max_stack;
56 this._flags = flags;
57 this._locals = locals;
58 this._stack = stack;
59 this._assert_unset_fields = assert_unset_fields;
60 this._verifier = v;
61 }
62
63 @Override
64 public String toString() {
65 return "frame @" + _offset + " with locals " + (_locals == null ? "[]" : Arrays.asList(_locals)) + " and stack " + (_stack == null ? "[]" : Arrays.asList(_stack));
66 }
67
68 void set_offset(int offset) {
69 this._offset = offset;
70 }
71
72 void set_flags(int flags) {
73 _flags = flags;
74 }
75
76 void set_locals_size(int locals_size) {
77 _locals_size = locals_size;
78 }
79
80 void set_stack_size(int stack_size) {
81 _stack_size = _stack_mark = stack_size;
82 }
83
84 int offset() {
85 return _offset;
86 }
87
88 VerifierImpl verifier() {
89 return _verifier;
90 }
91
92 int flags() {
93 return _flags;
94 }
95
96 int locals_size() {
97 return _locals_size;
98 }
99
100 VerificationType[] locals() {
101 return _locals;
102 }
103
104 int stack_size() {
105 return _stack_size;
106 }
107
108 VerificationType[] stack() {
109 return _stack;
110 }
111
112 int max_locals() {
113 return _max_locals;
114 }
115
116 boolean flag_this_uninit() {
117 return (_flags & FLAG_THIS_UNINIT) == FLAG_THIS_UNINIT;
118 }
119
120 Set<NameAndTypeEntry> assert_unset_fields() {
121 return _assert_unset_fields;
122 }
123
124 void set_assert_unset_fields(Set<NameAndTypeEntry> table) {
125 _assert_unset_fields = table;
126 }
127
128 // Called when verifying putfields to mark strict instance fields as satisfied
129 boolean satisfy_unset_field(Utf8Entry name, Utf8Entry signature) {
130 var nat = TemporaryConstantPool.INSTANCE.nameAndTypeEntry(name, signature);
131 return _assert_unset_fields.remove(nat);
132 }
133
134 // Verify that all strict fields have been initialized
135 // Strict fields must be initialized before the super constructor is called
136 boolean verify_unset_fields_satisfied() {
137 return _assert_unset_fields.isEmpty();
138 }
139
140 // Merge incoming unset strict fields from StackMapTable with
141 // initial strict instance fields
142 Set<NameAndTypeEntry> merge_unset_fields(Set<NameAndTypeEntry> new_fields) {
143 // ClassFile API: We track all strict fields in another structure, noop here
144 return new_fields;
145 }
146
147 boolean verify_unset_fields_compatibility(Set<NameAndTypeEntry> target_table) {
148 for (var e : _assert_unset_fields) {
149 if (!target_table.contains(e))
150 return false;
151 }
152 return true;
153 }
154
155 void unsatisfied_strict_fields_error(VerificationWrapper klass, int bci) {
156 _verifier.verifyError("All strict final fields must be initialized before super(): %d field(s), %s"
157 .formatted(_assert_unset_fields.size(), _assert_unset_fields));
158 }
159
160 void print_strict_fields(Set<NameAndTypeEntry> table) {
161 // ignore, we don't do stdout/err
162 }
163
164 void reset() {
165 for (int i = 0; i < _max_locals; i++) {
166 _locals[i] = VerificationType.bogus_type;
167 }
168 for (int i = 0; i < _max_stack; i++) {
169 _stack[i] = VerificationType.bogus_type;
170 }
171 }
172
173 void set_mark() {
174 if (_stack_mark != -1) {
175 for (int i = _stack_mark - 1; i >= _stack_size; --i) {
176 _stack[i] = VerificationType.bogus_type;
177 }
178 _stack_mark = _stack_size;
179 }
180 }
181
182 void push_stack(VerificationType type) {
183 if (type.is_check()) _verifier.verifyError("Must be a real type");
184 if (_stack_size >= _max_stack) {
185 _verifier.verifyError("Operand stack overflow");
186 }
187 _stack[_stack_size++] = type;
188 }
189
190 void push_stack_2(VerificationType type1, VerificationType type2) {
191 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double");
192 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2");
193 if (_stack_size >= _max_stack - 1) {
194 _verifier.verifyError("Operand stack overflow");
195 }
196 _stack[_stack_size++] = type1;
197 _stack[_stack_size++] = type2;
198 }
199
200 VerificationType pop_stack() {
201 if (_stack_size <= 0) {
202 _verifier.verifyError("Operand stack underflow");
203 }
204 return _stack[--_stack_size];
205 }
206
207 VerificationType pop_stack(VerificationType type) {
208 if (_stack_size != 0) {
209 VerificationType top = _stack[_stack_size - 1];
210 boolean subtype = type.is_assignable_from(top, verifier());
211 if (subtype) {
212 --_stack_size;
213 return top;
214 }
215 }
216 return pop_stack_ex(type);
217 }
218
219 void pop_stack_2(VerificationType type1, VerificationType type2) {
220 if (!(type1.is_long2() || type1.is_double2())) _verifier.verifyError("must be long/double");
221 if (!(type2.is_long() || type2.is_double())) _verifier.verifyError("must be long/double_2");
222 if (_stack_size >= 2) {
223 VerificationType top1 = _stack[_stack_size - 1];
224 boolean subtype1 = type1.is_assignable_from(top1, verifier());
225 VerificationType top2 = _stack[_stack_size - 2];
226 boolean subtype2 = type2.is_assignable_from(top2, verifier());
227 if (subtype1 && subtype2) {
228 _stack_size -= 2;
229 return;
230 }
231 }
232 pop_stack_ex(type1);
233 pop_stack_ex(type2);
234 }
235
236 VerificationFrame(int max_locals, int max_stack, Set<NameAndTypeEntry> initial_strict_fields, VerifierImpl verifier) {
237 _offset = 0;
238 _locals_size = 0;
239 _stack_size = 0;
240 _stack_mark = 0;
241 _max_locals = max_locals;
242 _max_stack = max_stack;
243 _flags = 0;
244 _verifier = verifier;
245 _locals = new VerificationType[max_locals];
246 _stack = new VerificationType[max_stack];
247 for (int i = 0; i < max_locals; i++) {
248 _locals[i] = VerificationType.bogus_type;
249 }
250 for (int i = 0; i < max_stack; i++) {
251 _stack[i] = VerificationType.bogus_type;
252 }
253 _assert_unset_fields = initial_strict_fields;
254 }
255
256 VerificationFrame frame_in_exception_handler(int flags) {
257 return new VerificationFrame(_offset, flags, _locals_size, 0,
258 _max_locals, _max_stack, _locals, new VerificationType[1],
259 _assert_unset_fields, _verifier);
260 }
261
262 void initialize_object(VerificationType old_object, VerificationType new_object) {
263 int i;
264 for (i = 0; i < _max_locals; i++) {
265 if (_locals[i].equals(old_object)) {
266 _locals[i] = new_object;
267 }
268 }
269 for (i = 0; i < _stack_size; i++) {
270 if (_stack[i].equals(old_object)) {
271 _stack[i] = new_object;
272 }
273 }
274 if (old_object.is_uninitialized_this(_verifier)) {
275 _flags = 0;
276 }
277 }
278
279 VerificationType set_locals_from_arg(VerificationWrapper.MethodWrapper m, VerificationType thisKlass) {
280 var ss = new VerificationSignature(m.descriptor(), true, _verifier);
281 int init_local_num = 0;
282 if (!m.isStatic()) {
283 init_local_num++;
284 if (VerifierImpl.object_initializer_name.equals(m.name()) && !VerifierImpl.java_lang_Object.equals(thisKlass.name())) {
285 _locals[0] = VerificationType.uninitialized_this_type;
286 _flags |= FLAG_THIS_UNINIT;
287 } else {
288 _locals[0] = thisKlass;
289 }
290 }
291 while (!ss.atReturnType()) {
292 init_local_num += _verifier.change_sig_to_verificationType(ss, _locals, init_local_num);
293 ss.next();
294 }
295 _locals_size = init_local_num;
296 switch (ss.type()) {
297 case T_OBJECT:
298 case T_ARRAY:
299 {
300 String sig = ss.asSymbol();
301 return VerificationType.reference_type(sig);
302 }
303 case T_INT: return VerificationType.integer_type;
304 case T_BYTE: return VerificationType.byte_type;
305 case T_CHAR: return VerificationType.char_type;
306 case T_SHORT: return VerificationType.short_type;
307 case T_BOOLEAN: return VerificationType.boolean_type;
308 case T_FLOAT: return VerificationType.float_type;
309 case T_DOUBLE: return VerificationType.double_type;
310 case T_LONG: return VerificationType.long_type;
311 case T_VOID: return VerificationType.bogus_type;
312 default:
313 _verifier.verifyError("Should not reach here");
314 return VerificationType.bogus_type;
315 }
316 }
317
318 void copy_locals(VerificationFrame src) {
319 int len = src.locals_size() < _locals_size ? src.locals_size() : _locals_size;
320 if (len > 0) System.arraycopy(src.locals(), 0, _locals, 0, len);
321 }
322
323 void copy_stack(VerificationFrame src) {
324 int len = src.stack_size() < _stack_size ? src.stack_size() : _stack_size;
325 if (len > 0) System.arraycopy(src.stack(), 0, _stack, 0, len);
326 }
327
328 private int is_assignable_to(VerificationType[] from, VerificationType[] to, int len) {
329 int i = 0;
330 for (; i < len; i++) {
331 if (!to[i].is_assignable_from(from[i], verifier())) {
332 break;
333 }
334 }
335 return i;
336 }
337
338 boolean is_assignable_to(VerificationFrame target) {
339 if (_max_locals != target.max_locals()) {
340 _verifier.verifyError("Locals size mismatch", this, target);
341 }
342 if (_stack_size != target.stack_size()) {
343 _verifier.verifyError("Stack size mismatch", this, target);
344 }
345 int mismatch_loc;
346 mismatch_loc = is_assignable_to(_locals, target.locals(), target.locals_size());
347 if (mismatch_loc != target.locals_size()) {
348 _verifier.verifyError("Bad type", this, target);
349 }
350 mismatch_loc = is_assignable_to(_stack, target.stack(), _stack_size);
351 if (mismatch_loc != _stack_size) {
352 _verifier.verifyError("Bad type", this, target);
353 }
354
355 // Check that assert unset fields are compatible
356 boolean compatible = verify_unset_fields_compatibility(target.assert_unset_fields());
357 if (!compatible) {
358 print_strict_fields(assert_unset_fields());
359 print_strict_fields(target.assert_unset_fields());
360 _verifier.verifyError("Strict fields mismatch from %s to %s".formatted(
361 assert_unset_fields(), target.assert_unset_fields()), this, target);
362 return false;
363 }
364
365 if ((_flags | target.flags()) == target.flags()) {
366 return true;
367 } else {
368 _verifier.verifyError("Bad flags", this, target);
369 }
370 return false;
371 }
372
373 VerificationType pop_stack_ex(VerificationType type) {
374 if (_stack_size <= 0) {
375 _verifier.verifyError("Operand stack underflow");
376 }
377 VerificationType top = _stack[--_stack_size];
378 boolean subtype = type.is_assignable_from(top, verifier());
379 if (!subtype) {
380 _verifier.verifyError("Bad type on operand stack");
381 }
382 return top;
383 }
384
385 VerificationType get_local(int index, VerificationType type) {
386 if (index >= _max_locals) {
387 _verifier.verifyError("Local variable table overflow");
388 }
389 boolean subtype = type.is_assignable_from(_locals[index],
390 verifier());
391 if (!subtype) {
392 _verifier.verifyError("Bad local variable type");
393 }
394 if(index >= _locals_size) { _locals_size = index + 1; }
395 return _locals[index];
396 }
397
398 void get_local_2(int index, VerificationType type1, VerificationType type2) {
399 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double");
400 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2");
401 if (index >= _locals_size - 1) {
402 _verifier.verifyError("get long/double overflows locals");
403 }
404 boolean subtype = type1.is_assignable_from(_locals[index], verifier());
405 if (!subtype) {
406 _verifier.verifyError("Bad local variable type");
407 } else {
408 subtype = type2.is_assignable_from(_locals[index + 1], verifier());
409 if (!subtype) {
410 _verifier.verifyError("Bad local variable type");
411 }
412 }
413 }
414
415 void set_local(int index, VerificationType type) {
416 if (type.is_check()) _verifier.verifyError("Must be a real type");
417 if (index >= _max_locals) {
418 _verifier.verifyError("Local variable table overflow");
419 }
420 if (_locals[index].is_double() || _locals[index].is_long()) {
421 if ((index + 1) >= _locals_size) _verifier.verifyError("Local variable table overflow");
422 _locals[index + 1] = VerificationType.bogus_type;
423 }
424 if (_locals[index].is_double2() || _locals[index].is_long2()) {
425 if (index < 1) _verifier.verifyError("Local variable table underflow");
426 _locals[index - 1] = VerificationType.bogus_type;
427 }
428 _locals[index] = type;
429 if (index >= _locals_size) {
430 for (int i=_locals_size; i<index; i++) {
431 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type");
432 }
433 _locals_size = index + 1;
434 }
435 }
436
437 void set_local_2(int index, VerificationType type1, VerificationType type2) {
438 if (!(type1.is_long() || type1.is_double())) _verifier.verifyError("must be long/double");
439 if (!(type2.is_long2() || type2.is_double2())) _verifier.verifyError("must be long/double_2");
440 if (index >= _max_locals - 1) {
441 _verifier.verifyError("Local variable table overflow");
442 }
443 if (_locals[index+1].is_double() || _locals[index+1].is_long()) {
444 if ((index + 2) >= _locals_size) _verifier.verifyError("Local variable table overflow");
445 _locals[index + 2] = VerificationType.bogus_type;
446 }
447 if (_locals[index].is_double2() || _locals[index].is_long2()) {
448 if (index < 1) _verifier.verifyError("Local variable table underflow");
449 _locals[index - 1] = VerificationType.bogus_type;
450 }
451 _locals[index] = type1;
452 _locals[index+1] = type2;
453 if (index >= _locals_size - 1) {
454 for (int i=_locals_size; i<index; i++) {
455 if (_locals[i] != VerificationType.bogus_type) _verifier.verifyError("holes must be bogus type");
456 }
457 _locals_size = index + 2;
458 }
459 }
460 }