Skip to content

Commit d9b4799

Browse files
author
duke
committedFeb 19, 2025
Automatic merge of jdk:master into master
2 parents a6f8fd0 + 7631984 commit d9b4799

File tree

3 files changed

+152
-109
lines changed

3 files changed

+152
-109
lines changed
 

‎src/hotspot/share/classfile/stackMapTable.cpp

+116-87
Original file line numberDiff line numberDiff line change
@@ -29,38 +29,49 @@
2929
#include "oops/oop.inline.hpp"
3030
#include "runtime/handles.inline.hpp"
3131

32-
StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
33-
u2 max_locals, u2 max_stack,
34-
char* code_data, int code_len, TRAPS) {
35-
_code_length = code_len;
32+
StackMapTable::StackMapTable(StackMapReader* reader, TRAPS) {
33+
_code_length = reader->code_length();
3634
_frame_count = reader->get_frame_count();
3735
if (_frame_count > 0) {
38-
_frame_array = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
39-
StackMapFrame*, _frame_count);
40-
StackMapFrame* pre_frame = init_frame;
41-
for (int32_t i = 0; i < _frame_count; i++) {
42-
StackMapFrame* frame = reader->next(
43-
pre_frame, i == 0, max_locals, max_stack,
44-
CHECK_VERIFY(pre_frame->verifier()));
45-
_frame_array[i] = frame;
46-
int offset = frame->offset();
47-
if (offset >= code_len || code_data[offset] == 0) {
48-
frame->verifier()->verify_error(
49-
ErrorContext::bad_stackmap(i, frame),
50-
"StackMapTable error: bad offset");
51-
return;
36+
_frame_array = new GrowableArray<StackMapFrame*>(_frame_count);
37+
while (!reader->at_end()) {
38+
StackMapFrame* frame = reader->next(CHECK_VERIFY(reader->prev_frame()->verifier()));
39+
if (frame != nullptr) {
40+
_frame_array->push(frame);
5241
}
53-
pre_frame = frame;
5442
}
43+
reader->check_end(CHECK);
44+
// Correct frame count based on how many actual frames are generated
45+
_frame_count = _frame_array->length();
46+
}
47+
}
48+
49+
void StackMapReader::check_offset(StackMapFrame* frame) {
50+
int offset = frame->offset();
51+
if (offset >= _code_length || _code_data[offset] == 0) {
52+
_verifier->verify_error(ErrorContext::bad_stackmap(0, frame),
53+
"StackMapTable error: bad offset");
54+
}
55+
}
56+
57+
void StackMapReader::check_size(TRAPS) {
58+
if (_frame_count < _parsed_frame_count) {
59+
StackMapStream::stackmap_format_error("wrong attribute size", THREAD);
60+
}
61+
}
62+
63+
void StackMapReader::check_end(TRAPS) {
64+
assert(_stream->at_end(), "must be");
65+
if (_frame_count != _parsed_frame_count) {
66+
StackMapStream::stackmap_format_error("wrong attribute size", THREAD);
5567
}
56-
reader->check_end(CHECK);
5768
}
5869

5970
// This method is only called by method in StackMapTable.
6071
int StackMapTable::get_index_from_offset(int32_t offset) const {
6172
int i = 0;
6273
for (; i < _frame_count; i++) {
63-
if (_frame_array[i]->offset() == offset) {
74+
if (_frame_array->at(i)->offset() == offset) {
6475
return i;
6576
}
6677
}
@@ -95,7 +106,7 @@ bool StackMapTable::match_stackmap(
95106
return false;
96107
}
97108

98-
StackMapFrame *stackmap_frame = _frame_array[frame_index];
109+
StackMapFrame* stackmap_frame = _frame_array->at(frame_index);
99110
bool result = true;
100111
if (match) {
101112
// Has direct control flow from last instruction, need to match the two
@@ -137,16 +148,20 @@ void StackMapTable::print_on(outputStream* str) const {
137148
{
138149
streamIndentor si(str);
139150
for (int32_t i = 0; i < _frame_count; ++i) {
140-
_frame_array[i]->print_on(str);
151+
_frame_array->at(i)->print_on(str);
141152
}
142153
}
143154
str->print_cr(" }");
144155
}
145156

146-
StackMapReader::StackMapReader(ClassVerifier* v, StackMapStream* stream, char* code_data,
147-
int32_t code_len, TRAPS) :
148-
_verifier(v), _stream(stream),
149-
_code_data(code_data), _code_length(code_len) {
157+
StackMapReader::StackMapReader(ClassVerifier* v, StackMapStream* stream,
158+
char* code_data, int32_t code_len,
159+
StackMapFrame* init_frame,
160+
u2 max_locals, u2 max_stack, TRAPS) :
161+
_verifier(v), _stream(stream), _code_data(code_data),
162+
_code_length(code_len), _parsed_frame_count(0),
163+
_prev_frame(init_frame), _max_locals(max_locals),
164+
_max_stack(max_stack), _first(true) {
150165
methodHandle m = v->method();
151166
if (m->has_stackmap_table()) {
152167
_cp = constantPoolHandle(THREAD, m->constants());
@@ -210,45 +225,56 @@ VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) {
210225
return VerificationType::bogus_type();
211226
}
212227

213-
StackMapFrame* StackMapReader::next(
214-
StackMapFrame* pre_frame, bool first, u2 max_locals, u2 max_stack, TRAPS) {
228+
StackMapFrame* StackMapReader::next(TRAPS) {
229+
_parsed_frame_count++;
230+
check_size(CHECK_NULL);
231+
StackMapFrame* frame = next_helper(CHECK_VERIFY_(_verifier, nullptr));
232+
if (frame != nullptr) {
233+
check_offset(frame);
234+
_prev_frame = frame;
235+
}
236+
return frame;
237+
}
238+
239+
StackMapFrame* StackMapReader::next_helper(TRAPS) {
215240
StackMapFrame* frame;
216241
int offset;
217242
VerificationType* locals = nullptr;
218243
u1 frame_type = _stream->get_u1(CHECK_NULL);
219244
if (frame_type < 64) {
220245
// same_frame
221-
if (first) {
246+
if (_first) {
222247
offset = frame_type;
223248
// Can't share the locals array since that is updated by the verifier.
224-
if (pre_frame->locals_size() > 0) {
249+
if (_prev_frame->locals_size() > 0) {
225250
locals = NEW_RESOURCE_ARRAY_IN_THREAD(
226-
THREAD, VerificationType, pre_frame->locals_size());
251+
THREAD, VerificationType, _prev_frame->locals_size());
227252
}
228253
} else {
229-
offset = pre_frame->offset() + frame_type + 1;
230-
locals = pre_frame->locals();
254+
offset = _prev_frame->offset() + frame_type + 1;
255+
locals = _prev_frame->locals();
231256
}
232257
frame = new StackMapFrame(
233-
offset, pre_frame->flags(), pre_frame->locals_size(), 0,
234-
max_locals, max_stack, locals, nullptr, _verifier);
235-
if (first && locals != nullptr) {
236-
frame->copy_locals(pre_frame);
258+
offset, _prev_frame->flags(), _prev_frame->locals_size(), 0,
259+
_max_locals, _max_stack, locals, nullptr, _verifier);
260+
if (_first && locals != nullptr) {
261+
frame->copy_locals(_prev_frame);
237262
}
263+
_first = false;
238264
return frame;
239265
}
240266
if (frame_type < 128) {
241267
// same_locals_1_stack_item_frame
242-
if (first) {
268+
if (_first) {
243269
offset = frame_type - 64;
244270
// Can't share the locals array since that is updated by the verifier.
245-
if (pre_frame->locals_size() > 0) {
271+
if (_prev_frame->locals_size() > 0) {
246272
locals = NEW_RESOURCE_ARRAY_IN_THREAD(
247-
THREAD, VerificationType, pre_frame->locals_size());
273+
THREAD, VerificationType, _prev_frame->locals_size());
248274
}
249275
} else {
250-
offset = pre_frame->offset() + frame_type - 63;
251-
locals = pre_frame->locals();
276+
offset = _prev_frame->offset() + frame_type - 63;
277+
locals = _prev_frame->locals();
252278
}
253279
VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD(
254280
THREAD, VerificationType, 2);
@@ -259,13 +285,14 @@ StackMapFrame* StackMapReader::next(
259285
stack_size = 2;
260286
}
261287
check_verification_type_array_size(
262-
stack_size, max_stack, CHECK_VERIFY_(_verifier, nullptr));
288+
stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr));
263289
frame = new StackMapFrame(
264-
offset, pre_frame->flags(), pre_frame->locals_size(), stack_size,
265-
max_locals, max_stack, locals, stack, _verifier);
266-
if (first && locals != nullptr) {
267-
frame->copy_locals(pre_frame);
290+
offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size,
291+
_max_locals, _max_stack, locals, stack, _verifier);
292+
if (_first && locals != nullptr) {
293+
frame->copy_locals(_prev_frame);
268294
}
295+
_first = false;
269296
return frame;
270297
}
271298

@@ -279,16 +306,16 @@ StackMapFrame* StackMapReader::next(
279306

280307
if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
281308
// same_locals_1_stack_item_frame_extended
282-
if (first) {
309+
if (_first) {
283310
offset = offset_delta;
284311
// Can't share the locals array since that is updated by the verifier.
285-
if (pre_frame->locals_size() > 0) {
312+
if (_prev_frame->locals_size() > 0) {
286313
locals = NEW_RESOURCE_ARRAY_IN_THREAD(
287-
THREAD, VerificationType, pre_frame->locals_size());
314+
THREAD, VerificationType, _prev_frame->locals_size());
288315
}
289316
} else {
290-
offset = pre_frame->offset() + offset_delta + 1;
291-
locals = pre_frame->locals();
317+
offset = _prev_frame->offset() + offset_delta + 1;
318+
locals = _prev_frame->locals();
292319
}
293320
VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD(
294321
THREAD, VerificationType, 2);
@@ -299,27 +326,28 @@ StackMapFrame* StackMapReader::next(
299326
stack_size = 2;
300327
}
301328
check_verification_type_array_size(
302-
stack_size, max_stack, CHECK_VERIFY_(_verifier, nullptr));
329+
stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr));
303330
frame = new StackMapFrame(
304-
offset, pre_frame->flags(), pre_frame->locals_size(), stack_size,
305-
max_locals, max_stack, locals, stack, _verifier);
306-
if (first && locals != nullptr) {
307-
frame->copy_locals(pre_frame);
331+
offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size,
332+
_max_locals, _max_stack, locals, stack, _verifier);
333+
if (_first && locals != nullptr) {
334+
frame->copy_locals(_prev_frame);
308335
}
336+
_first = false;
309337
return frame;
310338
}
311339

312340
if (frame_type <= SAME_EXTENDED) {
313341
// chop_frame or same_frame_extended
314-
locals = pre_frame->locals();
315-
int length = pre_frame->locals_size();
342+
locals = _prev_frame->locals();
343+
int length = _prev_frame->locals_size();
316344
int chops = SAME_EXTENDED - frame_type;
317345
int new_length = length;
318-
u1 flags = pre_frame->flags();
346+
u1 flags = _prev_frame->flags();
319347
if (chops != 0) {
320348
new_length = chop(locals, length, chops);
321349
check_verification_type_array_size(
322-
new_length, max_locals, CHECK_VERIFY_(_verifier, nullptr));
350+
new_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr));
323351
// Recompute flags since uninitializedThis could have been chopped.
324352
flags = 0;
325353
for (int i=0; i<new_length; i++) {
@@ -329,7 +357,7 @@ StackMapFrame* StackMapReader::next(
329357
}
330358
}
331359
}
332-
if (first) {
360+
if (_first) {
333361
offset = offset_delta;
334362
// Can't share the locals array since that is updated by the verifier.
335363
if (new_length > 0) {
@@ -339,28 +367,28 @@ StackMapFrame* StackMapReader::next(
339367
locals = nullptr;
340368
}
341369
} else {
342-
offset = pre_frame->offset() + offset_delta + 1;
370+
offset = _prev_frame->offset() + offset_delta + 1;
343371
}
344372
frame = new StackMapFrame(
345-
offset, flags, new_length, 0, max_locals, max_stack,
373+
offset, flags, new_length, 0, _max_locals, _max_stack,
346374
locals, nullptr, _verifier);
347-
if (first && locals != nullptr) {
348-
frame->copy_locals(pre_frame);
375+
if (_first && locals != nullptr) {
376+
frame->copy_locals(_prev_frame);
349377
}
378+
_first = false;
350379
return frame;
351380
} else if (frame_type < SAME_EXTENDED + 4) {
352381
// append_frame
353382
int appends = frame_type - SAME_EXTENDED;
354-
int real_length = pre_frame->locals_size();
383+
int real_length = _prev_frame->locals_size();
355384
int new_length = real_length + appends*2;
356385
locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length);
357-
VerificationType* pre_locals = pre_frame->locals();
358-
int i;
359-
for (i=0; i<pre_frame->locals_size(); i++) {
386+
VerificationType* pre_locals = _prev_frame->locals();
387+
for (int i = 0; i < _prev_frame->locals_size(); i++) {
360388
locals[i] = pre_locals[i];
361389
}
362-
u1 flags = pre_frame->flags();
363-
for (i=0; i<appends; i++) {
390+
u1 flags = _prev_frame->flags();
391+
for (int i = 0; i < appends; i++) {
364392
locals[real_length] = parse_verification_type(&flags, CHECK_NULL);
365393
if (locals[real_length].is_category2()) {
366394
locals[real_length + 1] = locals[real_length].to_category2_2nd();
@@ -369,15 +397,16 @@ StackMapFrame* StackMapReader::next(
369397
++real_length;
370398
}
371399
check_verification_type_array_size(
372-
real_length, max_locals, CHECK_VERIFY_(_verifier, nullptr));
373-
if (first) {
400+
real_length, _max_locals, CHECK_VERIFY_(_verifier, nullptr));
401+
if (_first) {
374402
offset = offset_delta;
375403
} else {
376-
offset = pre_frame->offset() + offset_delta + 1;
404+
offset = _prev_frame->offset() + offset_delta + 1;
377405
}
378406
frame = new StackMapFrame(
379-
offset, flags, real_length, 0, max_locals,
380-
max_stack, locals, nullptr, _verifier);
407+
offset, flags, real_length, 0, _max_locals,
408+
_max_stack, locals, nullptr, _verifier);
409+
_first = false;
381410
return frame;
382411
}
383412
if (frame_type == FULL) {
@@ -389,8 +418,7 @@ StackMapFrame* StackMapReader::next(
389418
locals = NEW_RESOURCE_ARRAY_IN_THREAD(
390419
THREAD, VerificationType, locals_size*2);
391420
}
392-
int i;
393-
for (i=0; i<locals_size; i++) {
421+
for (int i = 0; i < locals_size; i++) {
394422
locals[real_locals_size] = parse_verification_type(&flags, CHECK_NULL);
395423
if (locals[real_locals_size].is_category2()) {
396424
locals[real_locals_size + 1] =
@@ -400,15 +428,15 @@ StackMapFrame* StackMapReader::next(
400428
++real_locals_size;
401429
}
402430
check_verification_type_array_size(
403-
real_locals_size, max_locals, CHECK_VERIFY_(_verifier, nullptr));
431+
real_locals_size, _max_locals, CHECK_VERIFY_(_verifier, nullptr));
404432
u2 stack_size = _stream->get_u2(CHECK_NULL);
405433
int real_stack_size = 0;
406434
VerificationType* stack = nullptr;
407435
if (stack_size > 0) {
408436
stack = NEW_RESOURCE_ARRAY_IN_THREAD(
409437
THREAD, VerificationType, stack_size*2);
410438
}
411-
for (i=0; i<stack_size; i++) {
439+
for (int i = 0; i < stack_size; i++) {
412440
stack[real_stack_size] = parse_verification_type(nullptr, CHECK_NULL);
413441
if (stack[real_stack_size].is_category2()) {
414442
stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd();
@@ -417,19 +445,20 @@ StackMapFrame* StackMapReader::next(
417445
++real_stack_size;
418446
}
419447
check_verification_type_array_size(
420-
real_stack_size, max_stack, CHECK_VERIFY_(_verifier, nullptr));
421-
if (first) {
448+
real_stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr));
449+
if (_first) {
422450
offset = offset_delta;
423451
} else {
424-
offset = pre_frame->offset() + offset_delta + 1;
452+
offset = _prev_frame->offset() + offset_delta + 1;
425453
}
426454
frame = new StackMapFrame(
427455
offset, flags, real_locals_size, real_stack_size,
428-
max_locals, max_stack, locals, stack, _verifier);
456+
_max_locals, _max_stack, locals, stack, _verifier);
457+
_first = false;
429458
return frame;
430459
}
431460

432461
_stream->stackmap_format_error(
433-
"reserved frame type", CHECK_VERIFY_(pre_frame->verifier(), nullptr));
462+
"reserved frame type", CHECK_VERIFY_(_prev_frame->verifier(), nullptr));
434463
return nullptr;
435464
}

‎src/hotspot/share/classfile/stackMapTable.hpp

+34-19
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,14 @@ class StackMapTable : public StackObj {
4444
// Widening the type and making it signed will help detect these.
4545
int32_t _code_length;
4646
int32_t _frame_count; // Stackmap frame count
47-
StackMapFrame** _frame_array;
47+
GrowableArray<StackMapFrame*>* _frame_array;
4848

4949
public:
50-
StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
51-
u2 max_locals, u2 max_stack,
52-
char* code_data, int code_len, TRAPS);
50+
StackMapTable(StackMapReader* reader, TRAPS);
5351

5452
inline int32_t get_frame_count() const { return _frame_count; }
5553
inline int get_offset(int index) const {
56-
return _frame_array[index]->offset();
54+
return _frame_array->at(index)->offset();
5755
}
5856

5957
// Match and/or update current_frame to the frame in stackmap table with
@@ -116,9 +114,25 @@ class StackMapReader : StackObj {
116114
char* _code_data;
117115
int32_t _code_length;
118116

119-
// information get from the attribute
120-
int32_t _frame_count; // frame count
117+
// information from the attribute
118+
int32_t _frame_count;
121119

120+
// Number of frames parsed
121+
int32_t _parsed_frame_count;
122+
123+
// Previous frame buffer
124+
StackMapFrame* _prev_frame;
125+
126+
// information from method
127+
u2 _max_locals;
128+
u2 _max_stack;
129+
130+
// Check if reading first entry
131+
bool _first;
132+
133+
StackMapFrame* next_helper(TRAPS);
134+
void check_offset(StackMapFrame* frame);
135+
void check_size(TRAPS);
122136
int32_t chop(VerificationType* locals, int32_t length, int32_t chops);
123137
VerificationType parse_verification_type(u1* flags, TRAPS);
124138
void check_verification_type_array_size(
@@ -141,18 +155,19 @@ class StackMapReader : StackObj {
141155

142156
public:
143157
// Constructor
144-
StackMapReader(ClassVerifier* v, StackMapStream* stream, char* code_data,
145-
int32_t code_len, TRAPS);
146-
147-
inline int32_t get_frame_count() const { return _frame_count; }
148-
StackMapFrame* next(StackMapFrame* pre_frame, bool first,
149-
u2 max_locals, u2 max_stack, TRAPS);
150-
151-
void check_end(TRAPS) {
152-
if (!_stream->at_end()) {
153-
StackMapStream::stackmap_format_error("wrong attribute size", CHECK);
154-
}
155-
}
158+
StackMapReader(ClassVerifier* v, StackMapStream* stream,
159+
char* code_data, int32_t code_len,
160+
StackMapFrame* init_frame,
161+
u2 max_locals, u2 max_stack, TRAPS);
162+
163+
inline int32_t get_frame_count() const { return _frame_count; }
164+
inline StackMapFrame* prev_frame() const { return _prev_frame; }
165+
inline char* code_data() const { return _code_data; }
166+
inline int32_t code_length() const { return _code_length; }
167+
inline bool at_end() const { return _stream->at_end(); }
168+
169+
StackMapFrame* next(TRAPS);
170+
void check_end(TRAPS);
156171
};
157172

158173
#endif // SHARE_CLASSFILE_STACKMAPTABLE_HPP

‎src/hotspot/share/classfile/verifier.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,8 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
736736

737737
Array<u1>* stackmap_data = m->stackmap_data();
738738
StackMapStream stream(stackmap_data);
739-
StackMapReader reader(this, &stream, code_data, code_length, THREAD);
740-
StackMapTable stackmap_table(&reader, &current_frame, max_locals, max_stack,
741-
code_data, code_length, CHECK_VERIFY(this));
739+
StackMapReader reader(this, &stream, code_data, code_length, &current_frame, max_locals, max_stack, THREAD);
740+
StackMapTable stackmap_table(&reader, CHECK_VERIFY(this));
742741

743742
LogTarget(Debug, verification) lt;
744743
if (lt.is_enabled()) {

0 commit comments

Comments
 (0)
Please sign in to comment.