Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcverify/staticverify.c
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2022 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include <string.h>
24
25
/* #include "bcvcfr.h" */
26
27
#include "cfreader.h"
28
#include "bcsizes.h"
29
#include "j9protos.h"
30
#include "vrfyconvert.h"
31
32
#include "ut_j9bcverify.h"
33
34
#define BYTECODE_START 1
35
#define STACKMAP_START 2
36
37
#define FATAL_CLASS_FORMAT_ERROR -1
38
#define FALLBACK_CLASS_FORMAT_ERROR -2
39
#define FALLBACK_VERIFY_ERROR -3
40
41
typedef struct StackmapExceptionDetails {
42
I_32 stackmapFrameIndex;
43
U_32 stackmapFrameBCI;
44
} StackmapExceptionDetails;
45
46
static IDATA checkMethodStructure (J9PortLibrary * portLib, J9CfrClassFile * classfile, UDATA methodIndex, U_8 * instructionMap, J9CfrError * error, U_32 flags, I_32 *hasRET);
47
static IDATA buildInstructionMap (J9CfrClassFile * classfile, J9CfrAttributeCode * code, U_8 * map, UDATA methodIndex, J9CfrError * error);
48
static IDATA checkBytecodeStructure (J9CfrClassFile * classfile, UDATA methodIndex, UDATA length, U_8 * map, J9CfrError * error, U_32 flags, I_32 *hasRET);
49
static IDATA checkStackMap (J9CfrClassFile* classfile, J9CfrMethod * method, J9CfrAttributeCode * code, U_8 * map, UDATA flags, StackmapExceptionDetails* exceptionDetails);
50
static I_32 checkStackMapEntries (J9CfrClassFile* classfile, J9CfrAttributeCode * code, U_8 * map, U_8 ** entries, UDATA slotCount, U_8 * end, UDATA checkAppendArraySize);
51
52
static IDATA
53
buildInstructionMap (J9CfrClassFile * classfile, J9CfrAttributeCode * code, U_8 * map, UDATA methodIndex, J9CfrError * error)
54
{
55
U_8 *bcStart;
56
U_8 *bcIndex;
57
U_8 *bcEnd;
58
UDATA bc, npairs, temp;
59
IDATA pc, high, low, tableSize;
60
U_16 errorType;
61
62
bcStart = code->code;
63
bcIndex = bcStart;
64
bcEnd = bcIndex + (code->codeLength * sizeof(U_8));
65
pc = 0;
66
while (bcIndex < bcEnd) {
67
bc = (UDATA) *bcIndex;
68
pc = bcIndex - bcStart;
69
map[pc] = BYTECODE_START;
70
if (bc < CFR_BC_tableswitch) {
71
/* short circuit the switch for always clean ones */
72
bcIndex += (sunJavaByteCodeRelocation[bc] & 7);
73
continue;
74
}
75
switch (bc) {
76
case CFR_BC_wide:
77
if (*(bcIndex + 1) == CFR_BC_iinc) {
78
bcIndex += 6;
79
} else {
80
bcIndex += 4;
81
}
82
break;
83
84
case CFR_BC_tableswitch:
85
bcIndex += (4 - (pc & 3));
86
bcIndex += 4;
87
low = (IDATA) NEXT_U32(temp, bcIndex);
88
high = (IDATA) NEXT_U32(temp, bcIndex);
89
tableSize = ((I_32)high - (I_32)low + 1);
90
if ((I_32)low > (I_32)high || tableSize <=0 || tableSize >= 16384){
91
errorType = J9NLS_CFR_ERR_BC_SWITCH_EMPTY__ID;
92
goto _leaveProc;
93
}
94
bcIndex += tableSize * 4;
95
/*
96
* If overflow occurred, bcIndex will be less than or equal to the bcIndex of the start of this bytecode.
97
* We need to check for this explicitly, as the (bcIndex < bcEnd) loop condition will not catch this case.
98
*/
99
if (bcIndex <= (bcStart + pc)) {
100
errorType = J9NLS_CFR_ERR_BC_INCOMPLETE__ID;
101
goto _leaveProc;
102
}
103
break;
104
105
case CFR_BC_lookupswitch:
106
bcIndex += (4 - (pc & 3));
107
bcIndex += 4;
108
low = (IDATA) NEXT_U32(npairs, bcIndex);
109
if ((I_32)low < 0) {
110
errorType = J9NLS_CFR_ERR_BC_SWITCH_NEGATIVE_COUNT__ID;
111
goto _leaveProc;
112
}
113
bcIndex += npairs * 8;
114
/*
115
* If overflow occurred, bcIndex will be less than or equal to the bcIndex of the start of this bytecode.
116
* We need to check for this explicitly, as the (bcIndex < bcEnd) loop condition will not catch this case.
117
*/
118
if (bcIndex <= (bcStart + pc)) {
119
errorType = J9NLS_CFR_ERR_BC_INCOMPLETE__ID;
120
goto _leaveProc;
121
}
122
break;
123
124
default:
125
if ((bc > CFR_BC_MaxDefined) || (bc == CFR_BC_breakpoint)) {
126
errorType = J9NLS_CFR_ERR_BC_UNKNOWN__ID;
127
goto _leaveProc;
128
}
129
bcIndex += (sunJavaByteCodeRelocation[bc] & 7);
130
}
131
}
132
133
134
return 0;
135
136
_leaveProc:
137
Trc_STV_buildInstructionMap_VerifyError(errorType, methodIndex, pc);
138
buildMethodError(error, errorType, CFR_ThrowVerifyError, (I_32)methodIndex, (U_32)pc, &classfile->methods[methodIndex], classfile->constantPool);
139
return -1;
140
}
141
142
143
144
/*
145
##class format checking
146
147
Walk the sun bytecodes checking for illegal branch targets and doing some constant pool verification
148
149
Invalid returns will cause us to modify the classfile in place such that the second pass of the verification can correctly
150
throw the error (unless it turns out to be dead code).
151
152
*/
153
154
static IDATA
155
checkBytecodeStructure (J9CfrClassFile * classfile, UDATA methodIndex, UDATA length, U_8 * map, J9CfrError * error, U_32 flags, I_32 *hasRET)
156
{
157
#define CHECK_END \
158
if(bcIndex > bcEnd) { \
159
errorType = J9NLS_CFR_ERR_BC_INCOMPLETE__ID; \
160
goto _verifyError; \
161
}
162
163
J9CfrAttributeCode *code;
164
J9CfrConstantPoolInfo *info;
165
J9CfrMethod *method;
166
IDATA target, start, i1, i2, result, tableSize;
167
U_8 *bcStart, *bcInstructionStart, *bcIndex, *bcEnd;
168
UDATA bc, index, u1, u2, i, maxLocals, cpCount, tag;
169
UDATA sigChar;
170
UDATA errorType = 0;
171
UDATA errorDataIndex = 0;
172
173
174
method = &(classfile->methods[methodIndex]);
175
sigChar = (UDATA) getReturnTypeFromSignature(classfile->constantPool[method->descriptorIndex].bytes, classfile->constantPool[method->descriptorIndex].slot1, NULL);
176
code = method->codeAttribute;
177
178
maxLocals = code->maxLocals;
179
cpCount = classfile->constantPoolCount;
180
181
bcStart = code->code;
182
bcEnd = bcStart + length;
183
bcIndex = bcStart;
184
bcInstructionStart = bcIndex;
185
while (bcIndex < bcEnd) {
186
BOOLEAN noZeroIndex = FALSE;
187
bcInstructionStart = bcIndex;
188
/* Don't need to check that an instruction is in the code range here as method entries
189
have 4 extra bytes at the end - exception and attribute counts so we won't exceed
190
bcEnd by more than 4 (switches and wide iinc handled separately) and just test after the loop */
191
NEXT_U8(bc, bcIndex);
192
switch (bc) {
193
case CFR_BC_nop:
194
case CFR_BC_aconst_null:
195
case CFR_BC_iconst_m1:
196
case CFR_BC_iconst_0:
197
case CFR_BC_iconst_1:
198
case CFR_BC_iconst_2:
199
case CFR_BC_iconst_3:
200
case CFR_BC_iconst_4:
201
case CFR_BC_iconst_5:
202
case CFR_BC_lconst_0:
203
case CFR_BC_lconst_1:
204
case CFR_BC_fconst_0:
205
case CFR_BC_fconst_1:
206
case CFR_BC_fconst_2:
207
case CFR_BC_dconst_0:
208
case CFR_BC_dconst_1:
209
break;
210
211
case CFR_BC_bipush:
212
bcIndex++;
213
break;
214
215
case CFR_BC_sipush:
216
bcIndex+=2;
217
break;
218
219
case CFR_BC_ldc:
220
case CFR_BC_ldc_w:
221
if (bc == CFR_BC_ldc) {
222
NEXT_U8(index, bcIndex);
223
} else {
224
NEXT_U16(index, bcIndex);
225
}
226
if ((!index) || (index >= cpCount)) {
227
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
228
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
229
errorDataIndex = index;
230
goto _verifyError;
231
}
232
233
info = &(classfile->constantPool[index]);
234
tag = (UDATA) info->tag;
235
{
236
switch (tag) {
237
case CFR_CONSTANT_Integer:
238
case CFR_CONSTANT_Float:
239
case CFR_CONSTANT_String:
240
break;
241
case CFR_CONSTANT_Class:
242
if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(5)) {
243
errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V49__ID;
244
errorDataIndex = index;
245
goto _verifyError;
246
}
247
break;
248
case CFR_CONSTANT_MethodType:
249
case CFR_CONSTANT_MethodHandle:
250
if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(7)) {
251
errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V51__ID;
252
errorDataIndex = index;
253
goto _verifyError;
254
}
255
break;
256
case CFR_CONSTANT_Dynamic:
257
{
258
J9CfrConstantPoolInfo *constantDynamicSignature = &classfile->constantPool[classfile->constantPool[info->slot2].slot2];
259
if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(11)) {
260
errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V55__ID;
261
errorDataIndex = index;
262
goto _verifyError;
263
} else if (('D' == constantDynamicSignature->bytes[0]) || ('J' == constantDynamicSignature->bytes[0])) {
264
errorType = J9NLS_CFR_ERR_BC_LDC_CONSTANT_DYNAMIC_RETURNS_LONG_OR_DOUBLE__ID;
265
errorDataIndex = index;
266
goto _verifyError;
267
}
268
}
269
break;
270
default:
271
errorType = J9NLS_CFR_ERR_BC_LDC_NOT_CONSTANT_OR_CONSTANT_DYNAMIC__ID;
272
errorDataIndex = index;
273
goto _verifyError;
274
}
275
}
276
break;
277
278
case CFR_BC_ldc2_w:
279
280
NEXT_U16(index, bcIndex);
281
/* Only check single slot index since Constant_Dynamic doesn't require double slots in the constant pool */
282
if ((!index) || (index >= cpCount)) {
283
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
284
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
285
errorDataIndex = index;
286
goto _verifyError;
287
}
288
info = &(classfile->constantPool[index]);
289
tag = (UDATA) info->tag;
290
291
if (CFR_CONSTANT_Dynamic == tag) {
292
J9CfrConstantPoolInfo *constantDynamicSignature = &classfile->constantPool[classfile->constantPool[info->slot2].slot2];
293
if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(11)) {
294
errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V55__ID;
295
errorDataIndex = index;
296
goto _verifyError;
297
} else if (('D' != constantDynamicSignature->bytes[0]) && ('J' != constantDynamicSignature->bytes[0])) {
298
errorType = J9NLS_CFR_ERR_BC_LDC2W_CONSTANT_DYNAMIC_NOT_LONG_OR_DOUBLE__ID;
299
errorDataIndex = index;
300
goto _verifyError;
301
}
302
} else if (index >= (cpCount - 1)) {
303
/* Not Constant_Dynamic entry, then must be a double slot constant,
304
* first check if second slot is valid before checking constant tag
305
*/
306
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
307
errorDataIndex = index;
308
goto _verifyError;
309
} else if ((CFR_CONSTANT_Double != tag) && (CFR_CONSTANT_Long != tag)) {
310
errorType = J9NLS_CFR_ERR_BC_LDC2W_NOT_CONSTANT_OR_CONSTANT_DYNAMIC__ID;
311
errorDataIndex = index;
312
goto _verifyError;
313
}
314
break;
315
316
case CFR_BC_iload:
317
case CFR_BC_fload:
318
case CFR_BC_aload:
319
NEXT_U8(index, bcIndex);
320
321
if (index >= maxLocals) {
322
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
323
/* Jazz 82615: Set the local variable index to show up in the error message framework */
324
errorDataIndex = index;
325
goto _verifyError;
326
}
327
break;
328
329
case CFR_BC_lload:
330
case CFR_BC_dload:
331
NEXT_U8(index, bcIndex);
332
333
if ((index + 1) >= maxLocals) {
334
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
335
/* Jazz 82615: Set the local variable index to show up in the error message framework */
336
errorDataIndex = index + 1;
337
goto _verifyError;
338
}
339
break;
340
341
case CFR_BC_iload_0:
342
case CFR_BC_iload_1:
343
case CFR_BC_iload_2:
344
case CFR_BC_iload_3:
345
index = bc - CFR_BC_iload_0;
346
if (index >= maxLocals) {
347
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
348
/* Jazz 82615: Set the local variable index to show up in the error message framework */
349
errorDataIndex = index;
350
goto _verifyError;
351
}
352
break;
353
354
case CFR_BC_lload_0:
355
case CFR_BC_lload_1:
356
case CFR_BC_lload_2:
357
case CFR_BC_lload_3:
358
index = bc - CFR_BC_lload_0;
359
if ((index + 1) >= maxLocals) {
360
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
361
/* Jazz 82615: Set the local variable index to show up in the error message framework */
362
errorDataIndex = index + 1;
363
goto _verifyError;
364
}
365
break;
366
367
case CFR_BC_fload_0:
368
case CFR_BC_fload_1:
369
case CFR_BC_fload_2:
370
case CFR_BC_fload_3:
371
index = bc - CFR_BC_fload_0;
372
if (index >= maxLocals) {
373
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
374
/* Jazz 82615: Set the local variable index to show up in the error message framework */
375
errorDataIndex = index;
376
goto _verifyError;
377
}
378
break;
379
380
case CFR_BC_dload_0:
381
case CFR_BC_dload_1:
382
case CFR_BC_dload_2:
383
case CFR_BC_dload_3:
384
index = bc - CFR_BC_dload_0;
385
if ((index + 1) >= maxLocals) {
386
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
387
/* Jazz 82615: Set the local variable index to show up in the error message framework */
388
errorDataIndex = index + 1;
389
goto _verifyError;
390
}
391
break;
392
393
case CFR_BC_aload_0:
394
if (!maxLocals) {
395
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
396
/* Jazz 82615: Set the local variable index to show up in the error message framework */
397
errorDataIndex = 0;
398
goto _verifyError;
399
}
400
break;
401
402
case CFR_BC_aload_1:
403
case CFR_BC_aload_2:
404
case CFR_BC_aload_3:
405
index = bc - CFR_BC_aload_0;
406
if (index >= maxLocals) {
407
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
408
/* Jazz 82615: Set the local variable index to show up in the error message framework */
409
errorDataIndex = index;
410
goto _verifyError;
411
}
412
break;
413
414
case CFR_BC_iaload:
415
case CFR_BC_laload:
416
case CFR_BC_faload:
417
case CFR_BC_daload:
418
case CFR_BC_aaload:
419
case CFR_BC_baload:
420
case CFR_BC_caload:
421
case CFR_BC_saload:
422
break;
423
424
case CFR_BC_istore:
425
case CFR_BC_fstore:
426
case CFR_BC_astore:
427
NEXT_U8(index, bcIndex);
428
429
if (index >= maxLocals) {
430
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
431
/* Jazz 82615: Set the local variable index to show up in the error message framework */
432
errorDataIndex = index;
433
goto _verifyError;
434
}
435
break;
436
437
case CFR_BC_lstore:
438
case CFR_BC_dstore:
439
NEXT_U8(index, bcIndex);
440
441
if ((index + 1) >= maxLocals) {
442
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
443
/* Jazz 82615: Set the local variable index to show up in the error message framework */
444
errorDataIndex = index + 1;
445
goto _verifyError;
446
}
447
break;
448
449
450
case CFR_BC_istore_0:
451
case CFR_BC_istore_1:
452
case CFR_BC_istore_2:
453
case CFR_BC_istore_3:
454
index = bc - CFR_BC_istore_0;
455
if (index >= maxLocals) {
456
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
457
/* Jazz 82615: Set the local variable index to show up in the error message framework */
458
errorDataIndex = index;
459
goto _verifyError;
460
}
461
break;
462
463
case CFR_BC_lstore_0:
464
case CFR_BC_lstore_1:
465
case CFR_BC_lstore_2:
466
case CFR_BC_lstore_3:
467
index = bc - CFR_BC_lstore_0;
468
if ((index + 1) >= maxLocals) {
469
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
470
/* Jazz 82615: Set the local variable index to show up in the error message framework */
471
errorDataIndex = index + 1;
472
goto _verifyError;
473
}
474
break;
475
476
case CFR_BC_fstore_0:
477
case CFR_BC_fstore_1:
478
case CFR_BC_fstore_2:
479
case CFR_BC_fstore_3:
480
index = bc - CFR_BC_fstore_0;
481
if (index >= maxLocals) {
482
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
483
/* Jazz 82615: Set the local variable index to show up in the error message framework */
484
errorDataIndex = index;
485
goto _verifyError;
486
}
487
break;
488
489
case CFR_BC_dstore_0:
490
case CFR_BC_dstore_1:
491
case CFR_BC_dstore_2:
492
case CFR_BC_dstore_3:
493
index = bc - CFR_BC_dstore_0;
494
if ((index + 1) >= maxLocals) {
495
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
496
/* Jazz 82615: Set the local variable index to show up in the error message framework */
497
errorDataIndex = index + 1;
498
goto _verifyError;
499
}
500
break;
501
502
case CFR_BC_astore_0:
503
case CFR_BC_astore_1:
504
case CFR_BC_astore_2:
505
case CFR_BC_astore_3:
506
index = bc - CFR_BC_astore_0;
507
if (index >= maxLocals) {
508
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
509
/* Jazz 82615: Set the local variable index to show up in the error message framework */
510
errorDataIndex = index;
511
goto _verifyError;
512
}
513
break;
514
515
case CFR_BC_iastore:
516
case CFR_BC_lastore:
517
case CFR_BC_fastore:
518
case CFR_BC_dastore:
519
case CFR_BC_aastore:
520
case CFR_BC_bastore:
521
case CFR_BC_castore:
522
case CFR_BC_sastore:
523
break;
524
525
case CFR_BC_pop:
526
case CFR_BC_pop2:
527
case CFR_BC_dup:
528
case CFR_BC_dup_x1:
529
case CFR_BC_dup_x2:
530
case CFR_BC_dup2:
531
case CFR_BC_dup2_x1:
532
case CFR_BC_dup2_x2:
533
case CFR_BC_swap:
534
break;
535
536
case CFR_BC_iadd:
537
case CFR_BC_ladd:
538
case CFR_BC_fadd:
539
case CFR_BC_dadd:
540
case CFR_BC_isub:
541
case CFR_BC_lsub:
542
case CFR_BC_fsub:
543
case CFR_BC_dsub:
544
case CFR_BC_imul:
545
case CFR_BC_lmul:
546
case CFR_BC_fmul:
547
case CFR_BC_dmul:
548
case CFR_BC_idiv:
549
case CFR_BC_ldiv:
550
case CFR_BC_fdiv:
551
case CFR_BC_ddiv:
552
case CFR_BC_irem:
553
case CFR_BC_lrem:
554
case CFR_BC_frem:
555
case CFR_BC_drem:
556
case CFR_BC_ineg:
557
case CFR_BC_lneg:
558
case CFR_BC_fneg:
559
case CFR_BC_dneg:
560
case CFR_BC_ishl:
561
case CFR_BC_lshl:
562
case CFR_BC_ishr:
563
case CFR_BC_lshr:
564
case CFR_BC_iushr:
565
case CFR_BC_lushr:
566
case CFR_BC_iand:
567
case CFR_BC_land:
568
case CFR_BC_ior:
569
case CFR_BC_lor:
570
case CFR_BC_ixor:
571
case CFR_BC_lxor:
572
break;
573
574
case CFR_BC_iinc:
575
NEXT_U8(u1, bcIndex);
576
bcIndex++;
577
if (u1 >= maxLocals) {
578
errorType = J9NLS_CFR_ERR_BC_IINC_INDEX__ID;
579
/* Jazz 82615: Set the local variable index to show up in the error message framework */
580
errorDataIndex = u1;
581
goto _verifyError;
582
}
583
break;
584
585
case CFR_BC_i2l:
586
case CFR_BC_i2f:
587
case CFR_BC_i2d:
588
case CFR_BC_l2i:
589
case CFR_BC_l2f:
590
case CFR_BC_l2d:
591
case CFR_BC_f2i:
592
case CFR_BC_f2l:
593
case CFR_BC_f2d:
594
case CFR_BC_d2i:
595
case CFR_BC_d2l:
596
case CFR_BC_d2f:
597
case CFR_BC_i2b:
598
case CFR_BC_i2c:
599
case CFR_BC_i2s:
600
break;
601
602
case CFR_BC_lcmp:
603
case CFR_BC_fcmpl:
604
case CFR_BC_fcmpg:
605
case CFR_BC_dcmpl:
606
case CFR_BC_dcmpg:
607
break;
608
609
case CFR_BC_jsr:
610
method->j9Flags |= CFR_J9FLAG_HAS_JSR;
611
classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;
612
noZeroIndex = TRUE;
613
614
/* fall through */
615
616
case CFR_BC_goto:
617
case CFR_BC_ifeq:
618
case CFR_BC_ifne:
619
case CFR_BC_iflt:
620
case CFR_BC_ifge:
621
case CFR_BC_ifgt:
622
case CFR_BC_ifle:
623
case CFR_BC_if_icmpeq:
624
case CFR_BC_if_icmpne:
625
case CFR_BC_if_icmplt:
626
case CFR_BC_if_icmpge:
627
case CFR_BC_if_icmpgt:
628
case CFR_BC_if_icmple:
629
case CFR_BC_if_acmpeq:
630
case CFR_BC_if_acmpne:
631
case CFR_BC_ifnull:
632
case CFR_BC_ifnonnull:
633
start = bcIndex - bcStart - 1;
634
NEXT_U16(index, bcIndex);
635
target = (I_16) index + start;
636
if ((U_32) target >= (U_32) length) {
637
errorType = J9NLS_CFR_ERR_BC_JUMP_OFFSET__ID;
638
goto _verifyError;
639
}
640
if (!map[target]) {
641
errorType = J9NLS_CFR_ERR_BC_JUMP_TARGET__ID;
642
goto _verifyError;
643
}
644
if (noZeroIndex && (0 == index)) {
645
errorType = J9NLS_CFR_ERR_BC_JUMP_RECURSIVE__ID;
646
goto _verifyError;
647
}
648
break;
649
650
case CFR_BC_ret:
651
*hasRET = 1;
652
method->j9Flags |= CFR_J9FLAG_HAS_JSR;
653
classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;
654
NEXT_U8(index, bcIndex);
655
if (index >= maxLocals) {
656
errorType = J9NLS_CFR_ERR_BC_RET_INDEX__ID;
657
goto _verifyError;
658
}
659
break;
660
661
case CFR_BC_tableswitch:
662
start = bcIndex - bcStart - 1;
663
i1 = 3 - (start & 3);
664
bcIndex += i1;
665
CHECK_END;
666
bcIndex -= i1;
667
for (i2 = 0; i2 < i1; i2++) {
668
NEXT_U8(index, bcIndex);
669
if ((0 != index)
670
&& (flags & CFR_Xfuture)
671
&& (classfile->majorVersion < CFR_MAJOR_VERSION_REQUIRING_STACKMAPS)
672
) {
673
errorType = J9NLS_CFR_ERR_BC_SWITCH_PAD__ID;
674
goto _verifyError;
675
}
676
}
677
678
bcIndex += 12;
679
CHECK_END;
680
bcIndex -= 12;
681
NEXT_U32(u1, bcIndex);
682
target = start + (I_32) u1;
683
if ((UDATA) target >= length) {
684
errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;
685
goto _verifyError;
686
}
687
if (!map[target]) {
688
errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;
689
goto _verifyError;
690
}
691
i1 = (I_32) NEXT_U32(u1, bcIndex);
692
i2 = (I_32) NEXT_U32(u2, bcIndex);
693
tableSize = i2 - i1 + 1;
694
if (i1 > i2 || tableSize <= 0 || tableSize >= 16384) {
695
errorType = J9NLS_CFR_ERR_BC_SWITCH_EMPTY__ID;
696
goto _verifyError;
697
}
698
699
bcIndex += tableSize * 4;
700
CHECK_END;
701
bcIndex -= tableSize * 4;
702
703
/* Count the entries */
704
i2 = tableSize;
705
for (i1 = 0; i1 < i2; i1++) {
706
NEXT_U32(u1, bcIndex);
707
target = start + (I_32) u1;
708
if ((UDATA) target >= length) {
709
errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;
710
goto _verifyError;
711
}
712
if (!map[target]) {
713
errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;
714
goto _verifyError;
715
}
716
}
717
break;
718
719
case CFR_BC_lookupswitch:
720
start = bcIndex - bcStart - 1;
721
i1 = 3 - (start & 3);
722
bcIndex += i1;
723
CHECK_END;
724
bcIndex -= i1;
725
for (i2 = 0; i2 < i1; i2++) {
726
NEXT_U8(index, bcIndex);
727
if ((0 != index)
728
&& (flags & CFR_Xfuture)
729
&& (classfile->majorVersion < CFR_MAJOR_VERSION_REQUIRING_STACKMAPS)
730
) {
731
errorType = J9NLS_CFR_ERR_BC_SWITCH_PAD__ID;
732
goto _verifyError;
733
}
734
}
735
736
bcIndex += 8;
737
CHECK_END;
738
bcIndex -= 8;
739
NEXT_U32(u1, bcIndex);
740
target = start + (I_32) u1;
741
if ((UDATA) target >= length) {
742
errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;
743
goto _verifyError;
744
}
745
if (!map[target]) {
746
errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;
747
goto _verifyError;
748
}
749
NEXT_U32(u1, bcIndex);
750
751
bcIndex += (I_32) u1 * 8;
752
CHECK_END;
753
bcIndex -= (I_32) u1 * 8;
754
755
for (i = 0; i < u1; i++) {
756
/* Skip over match/key part of match-offset pair. Match/key order is verified in the second verification pass */
757
NEXT_U32(u2, bcIndex);
758
759
target = start + (I_32) NEXT_U32(u2, bcIndex);
760
if ((UDATA) target >= length) {
761
errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;
762
goto _verifyError;
763
}
764
if (!map[target]) {
765
errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;
766
goto _verifyError;
767
}
768
}
769
break;
770
771
case CFR_BC_ireturn:
772
switch (sigChar) {
773
case 'B':
774
case 'C':
775
case 'I':
776
case 'S':
777
case 'Z':
778
break;
779
default:
780
/* fail, modify the bytecode to be incompatible in the second pass of verification */
781
if (sigChar != 'V') {
782
*(bcIndex - 1) = CFR_BC_return;
783
}
784
}
785
break;
786
787
case CFR_BC_lreturn:
788
if (sigChar != 'J') {
789
/* fail, modify the bytecode to be incompatible in the second pass of verification */
790
if (sigChar != 'V') {
791
*(bcIndex - 1) = CFR_BC_return;
792
}
793
}
794
break;
795
796
case CFR_BC_freturn:
797
if (sigChar != 'F') {
798
/* fail, modify the bytecode to be incompatible in the second pass of verification */
799
if (sigChar != 'V') {
800
*(bcIndex - 1) = CFR_BC_return;
801
}
802
}
803
break;
804
805
case CFR_BC_dreturn:
806
if (sigChar != 'D') {
807
/* fail, modify the bytecode to be incompatible in the second pass of verification */
808
if (sigChar != 'V') {
809
*(bcIndex - 1) = CFR_BC_return;
810
}
811
}
812
break;
813
814
case CFR_BC_areturn:
815
if (!IS_REF_OR_VAL_SIGNATURE(sigChar) && (sigChar != '[')) {
816
/* fail, modify the bytecode to be incompatible in the second pass of verification */
817
if (sigChar != 'V') {
818
*(bcIndex - 1) = CFR_BC_return;
819
}
820
}
821
break;
822
823
case CFR_BC_return:
824
/* do not modify the bytecode at all, if the return matches we're good, if it does not match it will fail as expected
825
if (sigChar != 'V') {
826
fail, modify the bytecode to be incompatible in the second pass of verification
827
*(bcIndex - 1) = CFR_BC_return; leaving it alone will cause this to fail
828
}
829
*/
830
break;
831
832
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
833
case CFR_BC_withfield:
834
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
835
case CFR_BC_getstatic:
836
case CFR_BC_putstatic:
837
case CFR_BC_getfield:
838
case CFR_BC_putfield:
839
NEXT_U16(index, bcIndex);
840
if ((!index) || (index >= cpCount)) {
841
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
842
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
843
errorDataIndex = index;
844
goto _verifyError;
845
}
846
info = &(classfile->constantPool[index]);
847
if (info->tag != CFR_CONSTANT_Fieldref) {
848
errorType = J9NLS_CFR_ERR_BC_NOT_FIELDREF__ID;
849
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
850
errorDataIndex = index;
851
goto _verifyError;
852
}
853
/* field signature has been already been checked by j9bcv_verifyClassStructure() */
854
break;
855
856
case CFR_BC_invokespecial:
857
case CFR_BC_invokevirtual:
858
case CFR_BC_invokestatic:
859
/* Implicitly includes invokehandle & invokehandlegeneric bytecodes
860
* as they haven't been split from invokevirtual yet */
861
NEXT_U16(index, bcIndex);
862
if ((!index) || (index >= cpCount)) {
863
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
864
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
865
errorDataIndex = index;
866
goto _verifyError;
867
}
868
info = &(classfile->constantPool[index]);
869
if (info->tag != CFR_CONSTANT_Methodref) {
870
BOOLEAN isJava8orLater = ((flags & BCT_MajorClassFileVersionMask) >= BCT_JavaMajorVersionShifted(8)) || J9_ARE_ANY_BITS_SET(flags, BCT_Unsafe);
871
872
if (isJava8orLater && (bc != CFR_BC_invokevirtual) && (info->tag == CFR_CONSTANT_InterfaceMethodref)) {
873
/* JVMS 4.9.1 Static Constraints:
874
* The indexbyte operands of each invokespecial and invokestatic instruction must represent
875
* a valid index into the constant_pool table. The constant pool entry referenced by that
876
* index must be either of type CONSTANT_Methodref or of type CONSTANT_InterfaceMethodref.
877
*/
878
/* Valid - take no action */
879
} else {
880
errorType = J9NLS_CFR_ERR_BC_NOT_METHODREF__ID;
881
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
882
errorDataIndex = index;
883
goto _verifyError;
884
}
885
}
886
index = info->slot2;
887
info = &(classfile->constantPool[classfile->constantPool[index].slot1]);
888
U_16 returnChar = getReturnTypeFromSignature(classfile->constantPool[classfile->constantPool[index].slot2].bytes, classfile->constantPool[classfile->constantPool[index].slot2].slot1, NULL);
889
if (info->bytes[0] == '<') {
890
if ((IS_QTYPE(returnChar) && (bc != CFR_BC_invokestatic))
891
|| (!IS_QTYPE(returnChar) && (bc != CFR_BC_invokespecial))
892
|| (info->tag != CFR_CONSTANT_Utf8)
893
|| !J9UTF8_DATA_EQUALS("<init>", 6, info->bytes, info->slot1)
894
) {
895
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID__ID;
896
goto _verifyError;
897
}
898
}
899
/* Check for '<init> returns V' already done in j9bcv_verifyClassStructure */
900
/* Check for 'argCount <= 255' already done in j9bcv_verifyClassStructure */
901
break;
902
903
case CFR_BC_invokeinterface:
904
{
905
IDATA argCount = 0;
906
907
NEXT_U16(index, bcIndex);
908
if ((!index) || (index >= cpCount)) {
909
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
910
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
911
errorDataIndex = index;
912
goto _verifyError;
913
}
914
info = &(classfile->constantPool[index]);
915
if (info->tag != CFR_CONSTANT_InterfaceMethodref) {
916
errorType = J9NLS_CFR_ERR_BC_NOT_INTERFACEMETHODREF__ID;
917
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
918
errorDataIndex = index;
919
goto _verifyError;
920
}
921
info = &(classfile->constantPool[info->slot2]);
922
if (classfile->constantPool[info->slot1].bytes[0] == '<') {
923
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID__ID;
924
goto _verifyError;
925
}
926
NEXT_U8(index, bcIndex);
927
if ((argCount = j9bcv_checkMethodSignature(&(classfile->constantPool[info->slot2]), TRUE)) == -1) {
928
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;
929
goto _verifyError;
930
}
931
/* Check for 'argCount <= 255' when checking CFR_CONSTANT_*Methodref */
932
if (argCount != ((IDATA) index - 1)) {
933
errorType = J9NLS_CFR_ERR_BC_METHOD_NARGS__ID;
934
goto _verifyError;
935
}
936
NEXT_U8(index, bcIndex);
937
if (index) {
938
errorType = J9NLS_CFR_ERR_BC_METHOD_RESERVED__ID;
939
goto _verifyError;
940
}
941
break;
942
}
943
944
case CFR_BC_invokedynamic:
945
NEXT_U16(index, bcIndex);
946
if ((0 == index) || (index >= cpCount)) {
947
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
948
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
949
errorDataIndex = index;
950
goto _verifyError;
951
}
952
info = &(classfile->constantPool[index]);
953
if (info->tag != CFR_CONSTANT_InvokeDynamic) {
954
errorType = J9NLS_CFR_ERR_BC_NOT_INVOKEDYNAMIC__ID;
955
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
956
errorDataIndex = index;
957
goto _verifyError;
958
}
959
info = &(classfile->constantPool[info->slot2]);
960
if (classfile->constantPool[info->slot1].bytes[0] == '<') {
961
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID__ID;
962
goto _verifyError;
963
}
964
/* TODO what other verification is required? */
965
NEXT_U16(index, bcIndex);
966
if (0 != index) {
967
errorType = J9NLS_CFR_ERR_BC_INVOKEDYNAMIC_RESERVED__ID;
968
goto _verifyError;
969
}
970
break;
971
972
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
973
case CFR_BC_aconst_init:
974
/* fall through */
975
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
976
case CFR_BC_new:
977
NEXT_U16(index, bcIndex);
978
if ((!index) || (index >= cpCount)) {
979
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
980
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
981
errorDataIndex = index;
982
goto _verifyError;
983
}
984
info = &(classfile->constantPool[index]);
985
if (info->tag != CFR_CONSTANT_Class) {
986
errorType = J9NLS_CFR_ERR_BC_NEW_NOT_CLASS__ID;
987
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
988
errorDataIndex = index;
989
goto _verifyError;
990
}
991
break;
992
993
case CFR_BC_newarray:
994
NEXT_U8(index, bcIndex);
995
if ((index < 4) || (index > 11)) {
996
errorType = J9NLS_CFR_ERR_BC_NEWARRAY_TYPE__ID;
997
goto _verifyError;
998
}
999
break;
1000
1001
case CFR_BC_anewarray:
1002
NEXT_U16(index, bcIndex);
1003
if ((!index) || (index >= cpCount)) {
1004
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
1005
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1006
errorDataIndex = index;
1007
goto _verifyError;
1008
}
1009
info = &(classfile->constantPool[index]);
1010
if (info->tag != CFR_CONSTANT_Class) {
1011
errorType = J9NLS_CFR_ERR_BC_ANEWARRAY_NOT_CLASS__ID;
1012
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1013
errorDataIndex = index;
1014
goto _verifyError;
1015
}
1016
break;
1017
1018
case CFR_BC_arraylength:
1019
break;
1020
1021
case CFR_BC_athrow:
1022
break;
1023
1024
case CFR_BC_checkcast:
1025
NEXT_U16(index, bcIndex);
1026
if ((!index) || (index >= cpCount)) {
1027
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
1028
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1029
errorDataIndex = index;
1030
goto _verifyError;
1031
}
1032
info = &(classfile->constantPool[index]);
1033
if (info->tag != CFR_CONSTANT_Class) {
1034
errorType = J9NLS_CFR_ERR_BC_CHECKCAST_NOT_CLASS__ID;
1035
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1036
errorDataIndex = index;
1037
goto _verifyError;
1038
}
1039
break;
1040
1041
case CFR_BC_instanceof:
1042
NEXT_U16(index, bcIndex);
1043
if ((!index) || (index >= cpCount)) {
1044
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
1045
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1046
errorDataIndex = index;
1047
goto _verifyError;
1048
}
1049
info = &(classfile->constantPool[index]);
1050
if (info->tag != CFR_CONSTANT_Class) {
1051
errorType = J9NLS_CFR_ERR_BC_INSTANCEOF_NOT_CLASS__ID;
1052
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1053
errorDataIndex = index;
1054
goto _verifyError;
1055
}
1056
break;
1057
1058
case CFR_BC_monitorenter:
1059
case CFR_BC_monitorexit:
1060
break;
1061
1062
case CFR_BC_wide:
1063
NEXT_U8(bc, bcIndex);
1064
switch (bc) {
1065
1066
case CFR_BC_iload:
1067
case CFR_BC_fload:
1068
case CFR_BC_aload:
1069
NEXT_U16(index, bcIndex);
1070
1071
if (index >= maxLocals) {
1072
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
1073
/* Jazz 82615: Set the local variable index to show up in the error message framework */
1074
errorDataIndex = index;
1075
goto _verifyError;
1076
}
1077
break;
1078
1079
case CFR_BC_lload:
1080
case CFR_BC_dload:
1081
NEXT_U16(index, bcIndex);
1082
1083
if ((index + 1) >= maxLocals) {
1084
errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;
1085
/* Jazz 82615: Set the local variable index to show up in the error message framework */
1086
errorDataIndex = index + 1;
1087
goto _verifyError;
1088
}
1089
break;
1090
1091
case CFR_BC_istore:
1092
case CFR_BC_fstore:
1093
case CFR_BC_astore:
1094
NEXT_U16(index, bcIndex);
1095
1096
if (index >= maxLocals) {
1097
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
1098
/* Jazz 82615: Set the local variable index to show up in the error message framework */
1099
errorDataIndex = index;
1100
goto _verifyError;
1101
}
1102
break;
1103
1104
case CFR_BC_lstore:
1105
case CFR_BC_dstore:
1106
NEXT_U16(index, bcIndex);
1107
1108
if ((index + 1) >= maxLocals) {
1109
errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;
1110
/* Jazz 82615: Set the local variable index to show up in the error message framework */
1111
errorDataIndex = index + 1;
1112
goto _verifyError;
1113
}
1114
break;
1115
1116
case CFR_BC_iinc:
1117
CHECK_END;
1118
NEXT_U16(u1, bcIndex);
1119
bcIndex+=2;
1120
if (u1 >= maxLocals) {
1121
errorType = J9NLS_CFR_ERR_BC_IINC_INDEX__ID;
1122
goto _verifyError;
1123
}
1124
break;
1125
1126
case CFR_BC_ret:
1127
*hasRET = 1;
1128
method->j9Flags |= CFR_J9FLAG_HAS_JSR;
1129
classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;
1130
NEXT_U16(index, bcIndex);
1131
if (index >= maxLocals) {
1132
errorType = J9NLS_CFR_ERR_BC_RET_INDEX__ID;
1133
goto _verifyError;
1134
}
1135
break;
1136
1137
default:
1138
errorType = J9NLS_CFR_ERR_BC_NOT_WIDE__ID;
1139
goto _verifyError;
1140
}
1141
break;
1142
1143
case CFR_BC_multianewarray:
1144
NEXT_U16(index, bcIndex);
1145
NEXT_U8(u1, bcIndex);
1146
if ((!index) || (index >= cpCount)) {
1147
errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;
1148
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1149
errorDataIndex = index;
1150
goto _verifyError;
1151
}
1152
info = &(classfile->constantPool[index]);
1153
if (info->tag != CFR_CONSTANT_Class) {
1154
errorType = J9NLS_CFR_ERR_BC_MULTI_NOT_CLASS__ID;
1155
/* Jazz 82615: Set the constant pool index to show up in the error message framework */
1156
errorDataIndex = index;
1157
goto _verifyError;
1158
}
1159
info = &(classfile->constantPool[info->slot1]);
1160
u2 = 0;
1161
while (info->bytes[u2] == '[')
1162
u2++;
1163
if (!u2) {
1164
errorType = J9NLS_CFR_ERR_BC_MULTI_NOT_ARRAY__ID;
1165
goto _verifyError;
1166
}
1167
if ((!u1) || (u1 > u2)) {
1168
errorType = J9NLS_CFR_ERR_BC_MULTI_DIMS__ID;
1169
goto _verifyError;
1170
}
1171
break;
1172
1173
case CFR_BC_jsr_w:
1174
method->j9Flags |= CFR_J9FLAG_HAS_JSR;
1175
classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;
1176
noZeroIndex = TRUE;
1177
1178
/* fall through */
1179
1180
case CFR_BC_goto_w:
1181
start = bcIndex - bcStart - 1;
1182
NEXT_U32(index, bcIndex);
1183
target = (I_32) index + start;
1184
if ((UDATA) target >= length) {
1185
errorType = J9NLS_CFR_ERR_BC_JUMP_OFFSET__ID;
1186
goto _verifyError;
1187
}
1188
if (!map[target]) {
1189
errorType = J9NLS_CFR_ERR_BC_JUMP_TARGET__ID;
1190
goto _verifyError;
1191
}
1192
if (noZeroIndex && (0 == index)) {
1193
errorType = J9NLS_CFR_ERR_BC_JUMP_RECURSIVE__ID;
1194
goto _verifyError;
1195
}
1196
break;
1197
1198
default:
1199
errorType = J9NLS_CFR_ERR_BC_UNKNOWN__ID;
1200
goto _verifyError;
1201
}
1202
}
1203
1204
CHECK_END;
1205
1206
result = 0;
1207
goto _leaveProc; /* All is well */
1208
1209
_verifyError:
1210
start = bcInstructionStart - bcStart;
1211
Trc_STV_checkBytecodeStructure_VerifyError(errorType, methodIndex, start);
1212
buildMethodErrorWithExceptionDetails(error,
1213
errorType,
1214
0,
1215
CFR_ThrowVerifyError,
1216
(I_32)methodIndex,
1217
(U_32)start,
1218
method,
1219
classfile->constantPool,
1220
(U_32)errorDataIndex,
1221
-1,
1222
0);
1223
result = -1;
1224
1225
_leaveProc:
1226
return result;
1227
1228
#undef CHECK_END
1229
}
1230
1231
1232
1233
/**
1234
* Check whether any verification error occurs when walking through the stack map
1235
* @param classfile - pointer to J9CfrClassFile
1236
* @param method - pointer to J9CfrMethod
1237
* @param code - pointer to J9CfrAttributeCode
1238
* @param map - pointer to the stack map of the specified method
1239
* @param flags - settings in verification
1240
* @param exceptionDetails - pointer to StackmapExceptionDetails
1241
* @return 0 on success; otherwise, return a specific error code.
1242
*/
1243
static IDATA
1244
checkStackMap (J9CfrClassFile* classfile, J9CfrMethod * method, J9CfrAttributeCode * code, U_8 * map, UDATA flags, StackmapExceptionDetails* exceptionDetails)
1245
{
1246
UDATA i;
1247
IDATA errorCode = 0;
1248
J9CfrAttribute* attribute;
1249
1250
for (i = 0; i < code->attributesCount; i++) {
1251
attribute = code->attributes[i];
1252
1253
if (attribute->tag == CFR_ATTRIBUTE_StackMapTable){
1254
J9CfrAttributeStackMap * stackMap = (J9CfrAttributeStackMap *) attribute;
1255
U_8* entries = stackMap->entries;
1256
UDATA length = (UDATA) stackMap->mapLength;
1257
U_8* end = entries + length;
1258
UDATA j = 0;
1259
UDATA offset = (UDATA) -1;
1260
J9CfrConstantPoolInfo* info = &classfile->constantPool[method->descriptorIndex];
1261
1262
for (j = 0; j < stackMap->numberOfEntries; j++) {
1263
U_8 frameType;
1264
UDATA delta;
1265
IDATA slotCount;
1266
UDATA checkAppendArraySize = FALSE;
1267
1268
if ((entries + 1) > end) {
1269
errorCode = FATAL_CLASS_FORMAT_ERROR;
1270
goto _failedCheck;
1271
}
1272
frameType = *entries++;
1273
1274
if (frameType < CFR_STACKMAP_SAME_LOCALS_1_STACK) {
1275
offset += (UDATA) frameType;
1276
} else if (frameType < CFR_STACKMAP_SAME_LOCALS_1_STACK_END) {
1277
offset += (UDATA) frameType - (UDATA) CFR_STACKMAP_SAME_LOCALS_1_STACK;
1278
} else if (frameType >= CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED) {
1279
if ((entries + 2) > end) {
1280
errorCode = FATAL_CLASS_FORMAT_ERROR;
1281
goto _failedCheck;
1282
}
1283
offset += NEXT_U16(delta, entries); /* move past delta */
1284
} else {
1285
/* illegal frame type */
1286
errorCode = FATAL_CLASS_FORMAT_ERROR;
1287
goto _failedCheck;
1288
}
1289
offset++;
1290
1291
/* Throw the VerifyError without delay in the case of bad offset so as to match the RI's behavior */
1292
if ((offset >= code->codeLength) || (0 == map[offset])) {
1293
errorCode = FALLBACK_VERIFY_ERROR;
1294
exceptionDetails->stackmapFrameIndex = (I_32)j;
1295
exceptionDetails->stackmapFrameBCI = (U_32)offset;
1296
goto _failedCheck;
1297
}
1298
1299
if (entries > end) {
1300
errorCode = FATAL_CLASS_FORMAT_ERROR;
1301
goto _failedCheck;
1302
}
1303
1304
if (frameType != CFR_STACKMAP_FULL) {
1305
/* Only executed with StackMapTable */
1306
slotCount = 0;
1307
if ((frameType >= CFR_STACKMAP_SAME_LOCALS_1_STACK) && (frameType <= CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED)) {
1308
slotCount = 1;
1309
1310
/* The stackmap entry is invalid if the size of stack (1 slot) exceeds the size of the max stack.*/
1311
if (code->maxStack < slotCount) {
1312
errorCode = FATAL_CLASS_FORMAT_ERROR;
1313
goto _failedCheck;
1314
}
1315
}
1316
if (frameType >= CFR_STACKMAP_CHOP_3) {
1317
slotCount = (IDATA) frameType - CFR_STACKMAP_APPEND_BASE;
1318
if (slotCount < 0) {
1319
slotCount = 0;
1320
}
1321
1322
if ((frameType >= CFR_STACKMAP_APPEND_1) && (frameType <= CFR_STACKMAP_APPEND_3)) {
1323
checkAppendArraySize = TRUE;
1324
}
1325
}
1326
} else {
1327
/* full frame */
1328
/* Executed with StackMap or StackMapTable */
1329
NEXT_U16(slotCount, entries); /* number_of_locals verified in checkStackMapEntries */
1330
errorCode = checkStackMapEntries (classfile, code, map, &entries, slotCount, end, checkAppendArraySize);
1331
if (0 != errorCode) {
1332
goto _failedCheck;
1333
}
1334
NEXT_U16(slotCount, entries); /* number_of_stack_items verified in checkStackMapEntries */
1335
}
1336
errorCode = checkStackMapEntries (classfile, code, map, &entries, slotCount, end, checkAppendArraySize);
1337
if (0 != errorCode) {
1338
goto _failedCheck;
1339
}
1340
}
1341
1342
if (entries != end) {
1343
/* extra bytes in the attribute */
1344
errorCode = FATAL_CLASS_FORMAT_ERROR;
1345
goto _failedCheck;
1346
}
1347
}
1348
}
1349
_failedCheck:
1350
if ((FALLBACK_CLASS_FORMAT_ERROR == errorCode)
1351
|| (FALLBACK_VERIFY_ERROR == errorCode)
1352
) {
1353
if ((classfile->majorVersion < CFR_MAJOR_VERSION_REQUIRING_STACKMAPS)
1354
&& (0 == (flags & J9_VERIFY_NO_FALLBACK))
1355
) {
1356
/* Hide the bad StackMap/StackMapTable attribute and error. Major version 51 and greater do not allow fallback to type inference */
1357
attribute->tag = CFR_ATTRIBUTE_Unknown;
1358
errorCode = 0;
1359
}
1360
}
1361
1362
return errorCode;
1363
}
1364
1365
1366
1367
static I_32
1368
checkStackMapEntries (J9CfrClassFile* classfile, J9CfrAttributeCode * code, U_8 * map, U_8 ** entries, UDATA slotCount, U_8 * end, UDATA checkAppendArraySize)
1369
{
1370
U_8* entry = *entries;
1371
U_8 entryType;
1372
U_16 offset;
1373
U_16 cpIndex;
1374
J9CfrConstantPoolInfo* cpBase = classfile->constantPool;
1375
U_32 cpCount = (U_32) classfile->constantPoolCount;
1376
/* append check */
1377
U_16 slotTypeCounter = 0;
1378
UDATA hasDoubleSlot = FALSE;
1379
1380
for (; slotCount; slotCount--) {
1381
if ((entry + 1) > end) {
1382
return FATAL_CLASS_FORMAT_ERROR;
1383
}
1384
entryType = *entry++;
1385
1386
if (entry > end) {
1387
return FATAL_CLASS_FORMAT_ERROR;
1388
}
1389
1390
if (entryType > CFR_STACKMAP_TYPE_NEW_OBJECT) {
1391
/* Unknown entry */
1392
return FATAL_CLASS_FORMAT_ERROR;
1393
}
1394
1395
if (entryType == CFR_STACKMAP_TYPE_NEW_OBJECT) {
1396
if ((entry + 2) > end) {
1397
return FATAL_CLASS_FORMAT_ERROR;
1398
}
1399
NEXT_U16(offset, entry);
1400
1401
if (offset >= code->codeLength) {
1402
return FALLBACK_CLASS_FORMAT_ERROR;
1403
}
1404
1405
if (map[offset] == 0) {
1406
/* invalid bytecode index */
1407
return FALLBACK_CLASS_FORMAT_ERROR;
1408
}
1409
1410
if (code->code[offset] != CFR_BC_new) {
1411
return FALLBACK_CLASS_FORMAT_ERROR;
1412
}
1413
1414
} else if (entryType == CFR_STACKMAP_TYPE_OBJECT) {
1415
if ((entry + 2) > end) {
1416
return FATAL_CLASS_FORMAT_ERROR;
1417
}
1418
NEXT_U16(cpIndex, entry);
1419
/* Check index is in range */
1420
if ((!cpIndex) || (cpIndex > cpCount)) {
1421
return FATAL_CLASS_FORMAT_ERROR;
1422
}
1423
/* Check index points to the right type of thing */
1424
if(cpBase[cpIndex].tag != CFR_CONSTANT_Class) {
1425
return FATAL_CLASS_FORMAT_ERROR;
1426
}
1427
}
1428
1429
/* A value of type long or double must occupy two consecutive local variables. Ensure that if there is a long or double entry in
1430
* an append frame maxLocals reflects the correct number of slots. An incorrect maxLocals value in all other cases will be handled
1431
* in bcverify.c */
1432
if (checkAppendArraySize) {
1433
slotTypeCounter += 1;
1434
if ((CFR_STACKMAP_TYPE_DOUBLE == entryType) || (CFR_STACKMAP_TYPE_LONG == entryType)) {
1435
hasDoubleSlot = TRUE;
1436
slotTypeCounter += 1;
1437
}
1438
if (hasDoubleSlot && (slotTypeCounter > code->maxLocals)) {
1439
return FATAL_CLASS_FORMAT_ERROR;
1440
}
1441
}
1442
}
1443
1444
*entries = entry;
1445
return 0;
1446
}
1447
1448
1449
/*
1450
##class format checking
1451
1452
Check the Method provided and determine the
1453
referenced constant pool entries.
1454
1455
@results is an array of size classfile->constantPoolCount.
1456
@instructionMap is a handle to a pointer. If non-null, an instruction
1457
map will be created at this location.
1458
1459
Returns 0 on success, -1 on structure problem (error set), -2 on out of memory.
1460
1461
*/
1462
1463
static IDATA
1464
checkMethodStructure (J9PortLibrary * portLib, J9CfrClassFile * classfile, UDATA methodIndex, U_8 * instructionMap, J9CfrError * error, U_32 flags, I_32 *hasRET)
1465
{
1466
J9CfrAttributeCode *code;
1467
J9CfrMethod *method;
1468
J9CfrConstantPoolInfo * info;
1469
U_8 *map = NULL;
1470
UDATA i;
1471
IDATA result;
1472
UDATA length, pc = 0;
1473
U_16 errorType;
1474
1475
PORT_ACCESS_FROM_PORT (portLib);
1476
1477
method = &(classfile->methods[methodIndex]);
1478
code = method->codeAttribute;
1479
if (!code) {
1480
if ((method->accessFlags & CFR_ACC_NATIVE) || (method->accessFlags & CFR_ACC_ABSTRACT)) {
1481
result = 0;
1482
goto _leaveProc;
1483
} else {
1484
errorType = J9NLS_CFR_ERR_CODE_MISSING__ID;
1485
goto _formatError;
1486
}
1487
}
1488
1489
length = code->codeLength;
1490
if (length == 0) {
1491
errorType = J9NLS_CFR_ERR_CODE_ARRAY_EMPTY__ID;
1492
goto _formatError;
1493
}
1494
1495
if (instructionMap) {
1496
map = instructionMap;
1497
} else {
1498
map = j9mem_allocate_memory(length, J9MEM_CATEGORY_CLASSES);
1499
if (map == NULL) {
1500
result = -2;
1501
goto _leaveProc;
1502
}
1503
}
1504
memset (map, 0, length);
1505
1506
if (buildInstructionMap (classfile, code, map, methodIndex, error)) {
1507
result = -1;
1508
goto _leaveProc;
1509
}
1510
1511
for (i = 0; i < code->exceptionTableLength; i++) {
1512
pc = code->exceptionTable[i].startPC;
1513
if (pc >= length) {
1514
errorType = J9NLS_CFR_ERR_HANDLER_START_PC__ID;
1515
goto _formatError;
1516
}
1517
if (!map[pc]) {
1518
errorType = J9NLS_CFR_ERR_HANDLER_START_TARGET__ID;
1519
goto _formatError;
1520
}
1521
pc = code->exceptionTable[i].endPC;
1522
if (pc > length) {
1523
errorType = J9NLS_CFR_ERR_HANDLER_END_PC__ID;
1524
goto _formatError;
1525
}
1526
if ((!map[pc]) && (pc != length)) {
1527
errorType = J9NLS_CFR_ERR_HANDLER_END_TARGET__ID;
1528
goto _formatError;
1529
}
1530
if (code->exceptionTable[i].startPC >= code->exceptionTable[i].endPC) {
1531
errorType = J9NLS_CFR_ERR_HANDLER_RANGE_EMPTY__ID;
1532
goto _formatError;
1533
}
1534
pc = code->exceptionTable[i].handlerPC;
1535
if (pc >= length) {
1536
errorType = J9NLS_CFR_ERR_HANDLER_PC__ID;
1537
goto _formatError;
1538
}
1539
if (!map[pc]) {
1540
errorType = J9NLS_CFR_ERR_HANDLER_TARGET__ID;
1541
goto _formatError;
1542
}
1543
}
1544
1545
/* Throw a class format error if we are given a static <init> method (otherwise later we will throw a verify error due to back stack shape) */
1546
info = &(classfile->constantPool[method->nameIndex]);
1547
if (method->accessFlags & CFR_ACC_STATIC) {
1548
U_16 returnChar = getReturnTypeFromSignature(classfile->constantPool[method->descriptorIndex].bytes, classfile->constantPool[method->descriptorIndex].slot1, NULL);
1549
if ((CFR_CONSTANT_Utf8 == info->tag)
1550
&& J9UTF8_DATA_EQUALS("<init>", 6, info->bytes, info->slot1)
1551
&& ((J9_IS_CLASSFILE_VALUETYPE(classfile) && !IS_QTYPE(returnChar))
1552
|| (!J9_IS_CLASSFILE_VALUETYPE(classfile) && IS_QTYPE(returnChar)))
1553
) {
1554
errorType = J9NLS_CFR_ERR_ILLEGAL_METHOD_MODIFIERS__ID;
1555
goto _formatError;
1556
}
1557
}
1558
1559
if ((flags & J9_VERIFY_IGNORE_STACK_MAPS) == 0) {
1560
StackmapExceptionDetails exceptionDetails;
1561
memset(&exceptionDetails, 0, sizeof(exceptionDetails));
1562
result = checkStackMap(classfile, method, code, map, flags, &exceptionDetails);
1563
if (result) {
1564
if (result == FALLBACK_VERIFY_ERROR) {
1565
errorType = J9NLS_CFR_ERR_INVALID_STACK_MAP_ATTRIBUTE__ID;
1566
Trc_STV_checkMethodStructure_VerifyError(errorType, methodIndex, pc);
1567
/* Jazz 82615: Store error data for stackmap frame when verification error occurs */
1568
buildMethodErrorWithExceptionDetails(error,
1569
errorType,
1570
0,
1571
CFR_ThrowVerifyError,
1572
(I_32)methodIndex,
1573
(U_32)pc,
1574
method,
1575
classfile->constantPool,
1576
0,
1577
exceptionDetails.stackmapFrameIndex,
1578
exceptionDetails.stackmapFrameBCI);
1579
result = -1;
1580
goto _leaveProc;
1581
} else {
1582
errorType = J9NLS_CFR_ERR_INVALID_STACK_MAP_ATTRIBUTE__ID;
1583
goto _formatError;
1584
}
1585
}
1586
}
1587
1588
result = checkBytecodeStructure (classfile, methodIndex, length, map, error, flags, hasRET);
1589
1590
if (result) {
1591
goto _leaveProc;
1592
}
1593
1594
/* Should check thrown exceptions. */
1595
1596
goto _leaveProc; /* All is well */
1597
1598
_formatError:
1599
Trc_STV_checkMethodStructure_FormatError(errorType, methodIndex);
1600
buildMethodError(error, errorType, CFR_ThrowClassFormatError, (I_32)methodIndex, (U_32)pc, method, classfile->constantPool);
1601
result = -1;
1602
goto _leaveProc;
1603
1604
1605
_leaveProc:
1606
if (map && (map != instructionMap)) {
1607
j9mem_free_memory (map);
1608
}
1609
1610
return result;
1611
}
1612
1613
1614
1615
/*
1616
##class format checking
1617
1618
Check the Method provided and determine the
1619
referenced constant pool entries.
1620
1621
Returns 0 on success, -1 on structure problem (error set), -2 on out of memory.
1622
1623
*/
1624
1625
IDATA
1626
j9bcv_verifyClassStructure (J9PortLibrary * portLib, J9CfrClassFile * classfile, U_8 * segment,
1627
U_8 * segmentLength, U_8 * freePointer, U_32 vmVersionShifted, U_32 flags, I_32 *hasRET)
1628
{
1629
UDATA i;
1630
IDATA isInit;
1631
IDATA result = 0;
1632
UDATA length = 0;
1633
U_16 errorType = 0;
1634
J9CfrConstantPoolInfo *info;
1635
J9CfrConstantPoolInfo *utf8;
1636
J9CfrMethod *method;
1637
1638
Trc_STV_j9bcv_verifyClassStructure_Entry(classfile->constantPool[classfile->constantPool[classfile->thisClass].slot1].slot1,
1639
classfile->constantPool[classfile->constantPool[classfile->thisClass].slot1].bytes);
1640
1641
for (i = 1; i < classfile->constantPoolCount; i++) {
1642
J9CfrConstantPoolInfo *nameAndSig;
1643
IDATA arity;
1644
UDATA end;
1645
IDATA argCount;
1646
1647
info = &classfile->constantPool[i];
1648
switch (info->tag) {
1649
case CFR_CONSTANT_Class:
1650
/* Must be a UTF8. */
1651
utf8 = &classfile->constantPool[info->slot1];
1652
arity = bcvCheckClassName(utf8);
1653
if (arity < 0) {
1654
errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;
1655
goto _formatError;
1656
}
1657
1658
if (arity > 0) { /* we have some sort of array */
1659
if (arity > 255) {
1660
errorType = J9NLS_CFR_ERR_TOO_MANY_DIMENSIONS__ID;
1661
goto _formatError;
1662
}
1663
end = utf8->slot1;
1664
1665
switch (utf8->bytes[arity]) {
1666
case 'L': /* object array */
1667
if (utf8->bytes[--end] != ';') {
1668
errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;
1669
goto _formatError;
1670
}
1671
break;
1672
case 'B': /* base type array */
1673
case 'C':
1674
case 'D':
1675
case 'F':
1676
case 'I':
1677
case 'J':
1678
case 'S':
1679
case 'Z':
1680
if (--end != (UDATA) arity) {
1681
errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;
1682
goto _formatError;
1683
}
1684
break;
1685
default:
1686
errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;
1687
goto _formatError;
1688
}
1689
}
1690
1691
break;
1692
1693
case CFR_CONSTANT_NameAndType:
1694
if (0 != (flags & CFR_Xfuture)) {
1695
/* TODO: use the flags field to determine if this entry has been verified already */
1696
utf8 = &classfile->constantPool[info->slot2]; /* get the descriptor */
1697
if ((U_8) '(' == (utf8->bytes)[0]) { /* method descriptor */
1698
if (bcvCheckMethodName(&classfile->constantPool[info->slot1]) < 0) {
1699
errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;
1700
goto _formatError;
1701
}
1702
if (j9bcv_checkMethodSignature(&classfile->constantPool[info->slot2], FALSE) < 0) {
1703
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;
1704
goto _formatError;
1705
}
1706
} else {
1707
result = j9bcv_checkFieldSignature(utf8, 0);
1708
if (result < 0) {
1709
if (result == -1) {
1710
errorType = J9NLS_CFR_ERR_BC_FIELD_INVALID_SIG__ID;
1711
goto _formatError;
1712
} else {
1713
errorType = J9NLS_CFR_ERR_TOO_MANY_DIMENSIONS__ID;
1714
goto _formatError;
1715
}
1716
} else {
1717
result = 0;
1718
}
1719
}
1720
}
1721
break;
1722
case CFR_CONSTANT_Dynamic: /* fall through */
1723
/* No static constraints defined (so far) on slot1 (bsmIndex) */
1724
case CFR_CONSTANT_Fieldref:
1725
nameAndSig = &classfile->constantPool[info->slot2];
1726
utf8 = &classfile->constantPool[nameAndSig->slot1];
1727
if (bcvCheckName(utf8)) {
1728
errorType = J9NLS_CFR_ERR_BAD_FIELD_NAME__ID;
1729
goto _formatError;
1730
}
1731
utf8 = &classfile->constantPool[nameAndSig->slot2];
1732
if ((result = j9bcv_checkFieldSignature(utf8, 0)) < 0) {
1733
if (result == -1) {
1734
errorType = J9NLS_CFR_ERR_BC_FIELD_INVALID_SIG__ID;
1735
goto _formatError;
1736
} else {
1737
errorType = J9NLS_CFR_ERR_TOO_MANY_DIMENSIONS__ID;
1738
goto _formatError;
1739
}
1740
} else {
1741
result = 0;
1742
}
1743
break;
1744
1745
case CFR_CONSTANT_InvokeDynamic:
1746
/* No static constraints defined (so far) on slot1 */
1747
case CFR_CONSTANT_Methodref:
1748
case CFR_CONSTANT_InterfaceMethodref:
1749
nameAndSig = &classfile->constantPool[info->slot2];
1750
utf8 = &classfile->constantPool[nameAndSig->slot1];
1751
isInit = bcvCheckMethodName(utf8);
1752
if ((isInit < 0) || ((CFR_METHOD_NAME_CLINIT == isInit) && (CFR_CONSTANT_Methodref == info->tag))) {
1753
errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;
1754
goto _formatError;
1755
}
1756
info = &classfile->constantPool[nameAndSig->slot2];
1757
if ((argCount = j9bcv_checkMethodSignature(info, TRUE)) < 0) {
1758
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;
1759
goto _formatError;
1760
}
1761
if (isInit) {
1762
U_16 returnChar = getReturnTypeFromSignature(info->bytes, info->slot1, NULL);
1763
if ((info->bytes[info->slot1 - 1] != 'V') && !IS_QTYPE(returnChar)) {
1764
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;
1765
goto _formatError;
1766
}
1767
}
1768
if (argCount > 255) {
1769
errorType = J9NLS_CFR_ERR_TOO_MANY_ARGS__ID;
1770
/* TODO: determine if this should be verifyError */
1771
goto _formatError;
1772
}
1773
break;
1774
1775
case CFR_CONSTANT_MethodType:
1776
if (j9bcv_checkMethodSignature(&classfile->constantPool[info->slot1], FALSE) < 0) {
1777
errorType = J9NLS_CFR_ERR_METHODTYPE_INVALID_SIG__ID;
1778
goto _formatError;
1779
}
1780
break;
1781
1782
case CFR_CONSTANT_MethodHandle:
1783
/* method kinds: confirm <init> only when REF_newInvokeSpecial */
1784
if ((info->slot1 >= MH_REF_INVOKEVIRTUAL) && (info->slot1 <= MH_REF_INVOKEINTERFACE)) {
1785
J9CfrConstantPoolInfo *methodref = &classfile->constantPool[info->slot2];
1786
nameAndSig = &classfile->constantPool[methodref->slot2];
1787
utf8 = &classfile->constantPool[nameAndSig->slot1];
1788
isInit = bcvIsInitOrClinit(utf8);
1789
if (CFR_METHOD_NAME_CLINIT == isInit) {
1790
errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;
1791
goto _formatError;
1792
}
1793
if (CFR_METHOD_NAME_INIT == isInit) {
1794
if (info->slot1 != MH_REF_NEWINVOKESPECIAL) {
1795
errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;
1796
goto _formatError;
1797
}
1798
}
1799
}
1800
break;
1801
1802
}
1803
}
1804
1805
for (i = 0; i < classfile->fieldsCount; i++) {
1806
J9CfrField *field = &classfile->fields[i];
1807
info = &classfile->constantPool[field->descriptorIndex];
1808
utf8 = &classfile->constantPool[field->nameIndex];
1809
if (j9bcv_checkFieldSignature(info, 0) < 0) {
1810
errorType = J9NLS_CFR_ERR_BC_FIELD_INVALID_SIG__ID;
1811
goto _formatError;
1812
}
1813
if (bcvCheckName(utf8) < 0) {
1814
errorType = J9NLS_CFR_ERR_BAD_FIELD_NAME__ID;
1815
goto _formatError;
1816
}
1817
}
1818
1819
/* walk the classfile methods list */
1820
for (i = 0; i < classfile->methodsCount; i++) {
1821
IDATA argCount = 0;
1822
1823
method = &(classfile->methods[i]);
1824
utf8 = &classfile->constantPool[method->nameIndex];
1825
if ((isInit = bcvCheckMethodName(utf8)) < 0) {
1826
info = utf8;
1827
errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;
1828
goto _formatError;
1829
}
1830
1831
info = &classfile->constantPool[method->descriptorIndex];
1832
argCount = j9bcv_checkMethodSignature(info, TRUE);
1833
if (argCount < 0) {
1834
errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;
1835
goto _formatError;
1836
}
1837
1838
/* The requirement for taking no arguments was introduced in Java SE 9.
1839
* In a class file whose version number is 51.0 or above, the method
1840
* has its ACC_STATIC flag set and takes no arguments.
1841
*/
1842
/* Leave this here to find usages of the following check:
1843
* J2SE_19 has been deprecated and replaced with J2SE_V11
1844
* if (J2SE_VERSION(vm) >= J2SE_V11) {
1845
*/
1846
if (vmVersionShifted >= BCT_JavaMajorVersionShifted(9)) {
1847
if (classfile->majorVersion >= 51) {
1848
if ((CFR_METHOD_NAME_CLINIT == isInit)
1849
&& (0 != argCount)
1850
) {
1851
errorType = J9NLS_CFR_ERR_CLINIT_ILLEGAL_SIGNATURE__ID;
1852
goto _formatError;
1853
}
1854
}
1855
}
1856
1857
if (0 == (method->accessFlags & CFR_ACC_STATIC)) {
1858
argCount++;
1859
}
1860
if (argCount > 255) {
1861
errorType = J9NLS_CFR_ERR_TOO_MANY_ARGS__ID;
1862
goto _formatError;
1863
}
1864
if (method->codeAttribute) {
1865
if (argCount > (I_32) method->codeAttribute->maxLocals) {
1866
errorType = J9NLS_CFR_ERR_MAX_LOCALS__ID;
1867
goto _formatError;
1868
}
1869
}
1870
if (isInit) {
1871
U_16 returnChar = getReturnTypeFromSignature(info->bytes, info->slot1, NULL);
1872
if ((J9_IS_CLASSFILE_VALUETYPE(classfile) && !IS_QTYPE(returnChar))
1873
|| (!J9_IS_CLASSFILE_VALUETYPE(classfile) && (info->bytes[info->slot1 - 1] != 'V'))
1874
) {
1875
Trc_STV_j9bcv_verifyClassStructure_MethodError(J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID, i);
1876
buildMethodError((J9CfrError *)segment, errorType, CFR_ThrowClassFormatError, (I_32) i, 0, method, classfile->constantPool);
1877
result = -1;
1878
goto _leaveProc;
1879
}
1880
}
1881
1882
if (method->codeAttribute) {
1883
length = method->codeAttribute->codeLength;
1884
}
1885
1886
if ((freePointer + length) < segmentLength) {
1887
result = checkMethodStructure(portLib, classfile, i, freePointer, (J9CfrError *) segment, flags, hasRET);
1888
} else {
1889
/* We should probably skip this -- since if we don't have enough memory, we should just bail */
1890
result = checkMethodStructure(portLib, classfile, i, NULL, (J9CfrError *) segment, flags, hasRET);
1891
}
1892
1893
if (result) {
1894
goto _leaveProc; /* Fail */
1895
}
1896
}
1897
1898
goto _leaveProc; /* All is well */
1899
1900
_formatError:
1901
Trc_STV_j9bcv_verifyClassStructure_ClassError(errorType, info->romAddress);
1902
buildError((J9CfrError *)segment, errorType, CFR_ThrowClassFormatError, info->romAddress);
1903
result = -1;
1904
1905
_leaveProc:
1906
Trc_STV_j9bcv_verifyClassStructure_Exit();
1907
return result;
1908
}
1909
1910