Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcutil/cfreader.c
5985 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 "cfreader.h"
24
#include "j9protos.h"
25
#include "j9user.h"
26
#include <string.h>
27
#include "ut_j9bcu.h"
28
#include "j9bcvnls.h"
29
#include "romphase.h"
30
#include "bcutil_internal.h"
31
#include "util_api.h"
32
33
/*
34
* Note: The attrlookup.h file contains a generated perfect hash table
35
* for fast lookup of known attributes. It is used by attributeTagFor().
36
*
37
* It was generated using the gperf utility via the following command line:
38
*
39
* gperf -CD -t attrlookup.gperf
40
*
41
* (The gperf utility is a perfect hash function generator that is readily available on Linux.)
42
*
43
*/
44
#include "attrlookup.h"
45
46
static I_32 checkAttributes (J9PortLibrary* portLib, J9CfrClassFile* classfile, J9CfrAttribute** attributes, U_32 attributesCount, U_8* segment, I_32 maxBootstrapMethodIndex, U_32 extra, U_32 flags);
47
static I_32 readAttributes (J9CfrClassFile * classfile, J9CfrAttribute *** pAttributes, U_32 attributesCount, U_8 * data, U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags, UDATA * syntheticFound);
48
static I_32 checkFields (J9PortLibrary* portLib, J9CfrClassFile * classfile, U_8 * segment, U_32 flags);
49
static U_8 attributeTagFor (J9CfrConstantPoolInfo *utf8, BOOLEAN stripDebugAttributes);
50
static I_32 readAnnotations (J9CfrClassFile * classfile, J9CfrAnnotation * pAnnotations, U_32 annotationCount, U_8 * data, U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags);
51
static I_32 readTypeAnnotation (J9CfrClassFile * classfile, J9CfrTypeAnnotation * pAnnotations, U_8 * data, U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags);
52
static I_32 readAnnotationElement (J9CfrClassFile * classfile, J9CfrAnnotationElement ** pAnnotationElement, U_8 * data, U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags);
53
static I_32 checkClassVersion (J9CfrClassFile* classfile, U_8* segment, U_32 vmVersionShifted, U_32 flags);
54
static BOOLEAN utf8EqualUtf8 (J9CfrConstantPoolInfo *utf8a, J9CfrConstantPoolInfo *utf8b);
55
static BOOLEAN utf8Equal (J9CfrConstantPoolInfo* utf8, char* string, UDATA length);
56
static I_32 readMethods (J9CfrClassFile* classfile, U_8* data, U_8* dataEnd, U_8* segment, U_8* segmentEnd, U_8** pIndex, U_8** pFreePointer, U_32 flags);
57
static I_32 readPool (J9CfrClassFile* classfile, U_8* data, U_8* dataEnd, U_8* segment, U_8* segmentEnd, U_8** pIndex, U_8** pFreePointer);
58
static I_32 checkDuplicateMembers (J9PortLibrary* portLib, J9CfrClassFile * classfile, U_8 * segment, U_32 flags, UDATA memberSize);
59
static I_32 checkPool (J9CfrClassFile* classfile, U_8* segment, U_8* poolStart, I_32 *maxBootstrapMethodIndex, U_32 flags);
60
static I_32 checkClass (J9PortLibrary *portLib, J9CfrClassFile* classfile, U_8* segment, U_32 endOfConstantPool, U_32 vmVersionShifted, U_32 flags);
61
static I_32 readFields (J9CfrClassFile* classfile, U_8* data, U_8* dataEnd, U_8* segment, U_8* segmentEnd, U_8** pIndex, U_8** pFreePointer, U_32 flags);
62
static I_32 checkMethods (J9PortLibrary* portLib, J9CfrClassFile* classfile, U_8* segment, U_32 vmVersionShifted, U_32 flags);
63
static BOOLEAN memberEqual (J9CfrClassFile * classfile, J9CfrMember* a, J9CfrMember* b);
64
static void sortMethodIndex(J9CfrConstantPoolInfo* constantPool, J9CfrMethod *list, IDATA start, IDATA end);
65
static IDATA compareMethodIDs(J9CfrConstantPoolInfo* constantPool, J9CfrMethod *a, J9CfrMethod *b);
66
static U_8* getUTF8Data(J9CfrConstantPoolInfo* constantPool, U_16 cpIndex);
67
static U_16 getUTF8Length(J9CfrConstantPoolInfo* constantPool, U_16 cpIndex);
68
69
#define OUTSIDE_CODE ((U_32) -1)
70
71
/* set DUP_TIMING to 1 to determine the best value
72
* for DUP_HASH_THRESHOLD on a particular
73
* platform
74
*/
75
#define DUP_TIMING 0
76
#define DUP_HASH_THRESHOLD 30
77
78
#define MAX_CONSTANT_POOL_SIZE 0xFFFF
79
80
/* mapping characters A..Z */
81
static const U_8 cpTypeCharConversion[] = {
82
0, CFR_CONSTANT_Integer, CFR_CONSTANT_Integer, CFR_CONSTANT_Double,
83
0, CFR_CONSTANT_Float, 0, 0,
84
CFR_CONSTANT_Integer, CFR_CONSTANT_Long, 0, CFR_CONSTANT_String,
85
0, 0, 0, 0,
86
0, 0, CFR_CONSTANT_Integer, 0,
87
0, 0, 0, 0,
88
0, CFR_CONSTANT_Integer};
89
90
/*
91
Compare a J9CfrConstantUtf8 to a C string.
92
*/
93
94
static BOOLEAN
95
utf8Equal(J9CfrConstantPoolInfo* utf8, char* string, UDATA length)
96
{
97
if ((utf8->tag !=CFR_CONSTANT_Utf8) || (utf8->slot1 != length)) {
98
return FALSE;
99
}
100
101
return memcmp(utf8->bytes, string, length) == 0;
102
}
103
104
105
/*
106
Compare an J9CfrConstantPoolInfo to the known attribute
107
names. Return a tag value for any known attribute,
108
0 for an unknown one.
109
*/
110
static U_8
111
attributeTagFor(J9CfrConstantPoolInfo *utf8, BOOLEAN stripDebugAttributes)
112
{
113
const struct AttribType *attribType = lookupKnownAttribute((const char *)utf8->bytes, (unsigned int)utf8->slot1);
114
115
if (NULL != attribType) {
116
return (stripDebugAttributes ? attribType->strippedAttribCode : attribType->attribCode);
117
}
118
119
return (U_8) (stripDebugAttributes
120
? CFR_ATTRIBUTE_StrippedUnknown
121
: CFR_ATTRIBUTE_Unknown);
122
}
123
124
125
/*
126
Read the attributes from the bytes in @data.
127
Returns 0 on success, non-zero on failure.
128
*/
129
130
static I_32
131
readAttributes(J9CfrClassFile * classfile, J9CfrAttribute *** pAttributes, U_32 attributesCount, U_8 * data,
132
U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags, UDATA * syntheticFound)
133
{
134
J9CfrAttribute **attributes = *pAttributes;
135
U_8 *index = *pIndex;
136
U_8 *freePointer = *pFreePointer;
137
J9CfrConstantPoolInfo *info;
138
J9CfrAttribute *attrib;
139
J9CfrAttributeCode *code;
140
J9CfrAttributeExceptions *exceptions;
141
J9CfrExceptionTableEntry *exception;
142
J9CfrAttributeInnerClasses *classes;
143
J9CfrParameterAnnotations *parameterAnnotations;
144
J9CfrTypeAnnotation *typeAnnotations = NULL;
145
J9CfrAttributeStackMap *stackMap;
146
J9CfrAttributeBootstrapMethods *bootstrapMethods;
147
J9CfrAttributeRecord *record;
148
J9CfrAttributePermittedSubclasses *permittedSubclasses;
149
#if JAVA_SPEC_VERSION >= 11
150
J9CfrAttributeNestHost *nestHost;
151
J9CfrAttributeNestMembers *nestMembers;
152
#endif /* JAVA_SPEC_VERSION >= 11 */
153
U_32 name, length;
154
U_32 tag, errorCode, offset;
155
U_8 *end;
156
U_32 address;
157
U_32 i, j, k;
158
I_32 result;
159
BOOLEAN sourceFileAttributeRead = FALSE;
160
BOOLEAN bootstrapMethodAttributeRead = FALSE;
161
BOOLEAN visibleTypeAttributeRead = FALSE;
162
BOOLEAN invisibleTypeAttributeRead = FALSE;
163
BOOLEAN sourceDebugExtensionRead = FALSE;
164
BOOLEAN annotationDefaultRead = FALSE;
165
BOOLEAN visibleAnnotationsRead = FALSE;
166
BOOLEAN invisibleAnnotationsRead = FALSE;
167
BOOLEAN visibleParameterAnnotationsRead = FALSE;
168
BOOLEAN invisibleParameterAnnotationsRead = FALSE;
169
BOOLEAN recordAttributeRead = FALSE;
170
BOOLEAN permittedSubclassesAttributeRead = FALSE;
171
#if JAVA_SPEC_VERSION >= 11
172
BOOLEAN nestAttributeRead = FALSE;
173
#endif /* JAVA_SPEC_VERSION >= 11 */
174
175
if (NULL != syntheticFound) {
176
*syntheticFound = FALSE;
177
}
178
for (i = 0; i < attributesCount; i++) {
179
address = (U_32) (index - data);
180
181
CHECK_EOF(6);
182
NEXT_U16(name, index);
183
NEXT_U32(length, index);
184
end = index + length;
185
186
if ((!name) || (name >= classfile->constantPoolCount)) {
187
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
188
offset = address;
189
goto _errorFound;
190
}
191
info = &classfile->constantPool[name];
192
if (info->tag != CFR_CONSTANT_Utf8) {
193
errorCode = J9NLS_CFR_ERR_BAD_NAME_INDEX__ID;
194
offset = address;
195
goto _errorFound;
196
}
197
tag = attributeTagFor(info, (BOOLEAN) (flags & CFR_StripDebugAttributes));
198
199
switch (tag) {
200
case CFR_ATTRIBUTE_SourceFile:
201
if (sourceFileAttributeRead){
202
errorCode = J9NLS_CFR_ERR_FOUND_MULTIPLE_SOURCE_FILE_ATTRIBUTES__ID;
203
offset = address;
204
goto _errorFound;
205
}
206
sourceFileAttributeRead = TRUE;
207
if (!ALLOC_CAST(attrib, J9CfrAttributeSourceFile, J9CfrAttribute)) {
208
return -2;
209
}
210
CHECK_EOF(2);
211
NEXT_U16(((J9CfrAttributeSourceFile *) attrib)->sourceFileIndex, index);
212
break;
213
214
case CFR_ATTRIBUTE_Signature:
215
if (!ALLOC_CAST(attrib, J9CfrAttributeSignature, J9CfrAttribute)) {
216
return -2;
217
}
218
CHECK_EOF(2);
219
NEXT_U16(((J9CfrAttributeSignature *) attrib)->signatureIndex, index);
220
break;
221
222
case CFR_ATTRIBUTE_ConstantValue:
223
if (!ALLOC_CAST(attrib, J9CfrAttributeConstantValue, J9CfrAttribute)) {
224
return -2;
225
}
226
CHECK_EOF(2);
227
NEXT_U16(((J9CfrAttributeConstantValue *) attrib)->constantValueIndex, index);
228
break;
229
230
case CFR_ATTRIBUTE_Code:
231
if (!ALLOC(code, J9CfrAttributeCode)) {
232
return -2;
233
}
234
attrib = (J9CfrAttribute*)code;
235
236
CHECK_EOF(8);
237
NEXT_U16(code->maxStack, index);
238
NEXT_U16(code->maxLocals, index);
239
NEXT_U32(code->codeLength, index);
240
241
CHECK_EOF(code->codeLength);
242
if (!ALLOC_ARRAY(code->code, code->codeLength, U_8)) {
243
return -2;
244
}
245
code->originalCode = index;
246
memcpy (code->code, index, code->codeLength);
247
index += code->codeLength;
248
249
CHECK_EOF(2);
250
NEXT_U16(code->exceptionTableLength, index);
251
if (!ALLOC_ARRAY(code->exceptionTable, code->exceptionTableLength, J9CfrExceptionTableEntry)) {
252
return -2;
253
}
254
CHECK_EOF(code->exceptionTableLength << 3);
255
for (j = 0; j < code->exceptionTableLength; j++) {
256
exception = &(code->exceptionTable[j]);
257
NEXT_U16(exception->startPC, index);
258
NEXT_U16(exception->endPC, index);
259
NEXT_U16(exception->handlerPC, index);
260
NEXT_U16(exception->catchType, index);
261
}
262
263
CHECK_EOF(2);
264
NEXT_U16(code->attributesCount, index);
265
if (!ALLOC_ARRAY(code->attributes, code->attributesCount, J9CfrAttribute *)) {
266
return -2;
267
}
268
if ((result = readAttributes(classfile, &(code->attributes), code->attributesCount, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags, NULL)) != 0) {
269
return result;
270
}
271
break;
272
273
case CFR_ATTRIBUTE_Exceptions:
274
if (!ALLOC(exceptions, J9CfrAttributeExceptions)) {
275
return -2;
276
}
277
attrib = (J9CfrAttribute*)exceptions;
278
CHECK_EOF(2);
279
NEXT_U16(exceptions->numberOfExceptions, index);
280
if (!ALLOC_ARRAY(exceptions->exceptionIndexTable, exceptions->numberOfExceptions, U_16)) {
281
return -2;
282
}
283
CHECK_EOF(exceptions->numberOfExceptions << 1);
284
for (j = 0; j < exceptions->numberOfExceptions; j++) {
285
NEXT_U16(exceptions->exceptionIndexTable[j], index);
286
}
287
break;
288
289
case CFR_ATTRIBUTE_LineNumberTable:
290
if (!ALLOC_CAST(attrib, J9CfrAttributeLineNumberTable, J9CfrAttribute)) {
291
return -2;
292
}
293
CHECK_EOF(2);
294
NEXT_U16(((J9CfrAttributeLineNumberTable *) attrib)->lineNumberTableLength, index);
295
if (!ALLOC_ARRAY(
296
((J9CfrAttributeLineNumberTable *) attrib)->lineNumberTable,
297
((J9CfrAttributeLineNumberTable *) attrib)->lineNumberTableLength,
298
J9CfrLineNumberTableEntry)) {
299
return -2;
300
}
301
302
CHECK_EOF(((J9CfrAttributeLineNumberTable *) attrib)->lineNumberTableLength << 2);
303
for (j = 0; j < ((J9CfrAttributeLineNumberTable *) attrib)->lineNumberTableLength; j++) {
304
NEXT_U16(((J9CfrAttributeLineNumberTable *) attrib)->lineNumberTable[j].startPC, index);
305
NEXT_U16(((J9CfrAttributeLineNumberTable *) attrib)->lineNumberTable[j].lineNumber, index);
306
}
307
break;
308
309
case CFR_ATTRIBUTE_LocalVariableTable:
310
if (!ALLOC_CAST(attrib, J9CfrAttributeLocalVariableTable, J9CfrAttribute)) {
311
return -2;
312
}
313
CHECK_EOF(2);
314
NEXT_U16(((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTableLength, index);
315
if (!ALLOC_ARRAY(
316
((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTable,
317
((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTableLength,
318
J9CfrLocalVariableTableEntry)) {
319
return -2;
320
}
321
322
CHECK_EOF(((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTableLength * 10);
323
for (j = 0; j < ((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTableLength; j++) {
324
NEXT_U16(((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTable[j].startPC, index);
325
NEXT_U16(((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTable[j].length, index);
326
NEXT_U16(((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTable[j].nameIndex, index);
327
NEXT_U16(((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTable[j].descriptorIndex, index);
328
NEXT_U16(((J9CfrAttributeLocalVariableTable *) attrib)->localVariableTable[j].index, index);
329
}
330
break;
331
332
case CFR_ATTRIBUTE_LocalVariableTypeTable:
333
if (!ALLOC_CAST(attrib, J9CfrAttributeLocalVariableTypeTable, J9CfrAttribute)) {
334
return -2;
335
}
336
CHECK_EOF(2);
337
NEXT_U16(((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTableLength, index);
338
if (!ALLOC_ARRAY(
339
((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTable,
340
((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTableLength,
341
J9CfrLocalVariableTypeTableEntry)) {
342
return -2;
343
}
344
345
CHECK_EOF(((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTableLength * 10);
346
for (j = 0; j < ((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTableLength; j++) {
347
NEXT_U16(((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTable[j].startPC, index);
348
NEXT_U16(((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTable[j].length, index);
349
NEXT_U16(((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTable[j].nameIndex, index);
350
NEXT_U16(((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTable[j].signatureIndex, index);
351
NEXT_U16(((J9CfrAttributeLocalVariableTypeTable *) attrib)->localVariableTypeTable[j].index, index);
352
}
353
break;
354
355
case CFR_ATTRIBUTE_Synthetic:
356
if (!ALLOC_CAST(attrib, J9CfrAttributeSynthetic, J9CfrAttribute)) {
357
return -2;
358
}
359
CHECK_EOF(length);
360
index += length;
361
if (NULL != syntheticFound) {
362
*syntheticFound = TRUE;
363
}
364
break;
365
366
case CFR_ATTRIBUTE_AnnotationDefault: {
367
if (annotationDefaultRead) {
368
/* found a redundant attribute */
369
errorCode = J9NLS_CFR_ERR_MULTIPLE_ANNOTATION_DEFAULT_ATTRIBUTES__ID;
370
offset = address;
371
goto _errorFound;
372
373
} else {
374
annotationDefaultRead = TRUE;
375
}
376
if (!ALLOC_CAST(attrib, J9CfrAttributeAnnotationDefault, J9CfrAttribute)) {
377
return -2;
378
}
379
380
result = readAnnotationElement(classfile, &((J9CfrAttributeAnnotationDefault *)attrib)->defaultValue,
381
data, dataEnd, segment, segmentEnd, &index, &freePointer, flags);
382
if (result != 0) {
383
return result;
384
}
385
}
386
break;
387
388
case CFR_ATTRIBUTE_RuntimeInvisibleAnnotations:
389
if (invisibleAnnotationsRead) {
390
/* found a redundant attribute */
391
errorCode = J9NLS_CFR_ERR_MULTIPLE_ANNOTATION_ATTRIBUTES__ID;
392
offset = address;
393
goto _errorFound;
394
395
} else {
396
invisibleAnnotationsRead = TRUE;
397
}
398
if (J9_ARE_NO_BITS_SET(flags, BCT_RetainRuntimeInvisibleAttributes)) {
399
if (!ALLOC(attrib, J9CfrAttribute)) { /* create dummy attribute and skip */
400
return BCT_ERR_OUT_OF_ROM;
401
}
402
CHECK_EOF(length);
403
index += length;
404
break;
405
} /* else FALLTHROUGH */
406
case CFR_ATTRIBUTE_RuntimeVisibleAnnotations: {
407
U_8 *attributeStart = index;
408
J9CfrAttributeRuntimeVisibleAnnotations *annotations = NULL;
409
if (CFR_ATTRIBUTE_RuntimeVisibleAnnotations == tag) {
410
if (visibleAnnotationsRead) {
411
/* found a redundant attribute */
412
errorCode = J9NLS_CFR_ERR_MULTIPLE_ANNOTATION_ATTRIBUTES__ID;
413
offset = address;
414
goto _errorFound;
415
}
416
visibleAnnotationsRead = TRUE;
417
}
418
if (!ALLOC_CAST(attrib, J9CfrAttributeRuntimeVisibleAnnotations, J9CfrAttribute)) {
419
return BCT_ERR_OUT_OF_ROM;
420
}
421
422
annotations = (J9CfrAttributeRuntimeVisibleAnnotations *)attrib;
423
annotations->numberOfAnnotations = 0;
424
annotations->annotations = NULL;
425
annotations->rawAttributeData = NULL;
426
annotations->rawDataLength = 0; /* 0 indicates attribute is well-formed */
427
428
/* In the case of a malformed attribute numberOfAnnotations may not exist even if the file did not end.
429
* There must be at least two bytes to have a valid numberOfAnnotations.
430
* Length of 0 will be treated as an error below. Length of 1 will be an error as well since the index
431
* will not match the end value.
432
*/
433
if (length > 1) {
434
CHECK_EOF(2);
435
NEXT_U16(annotations->numberOfAnnotations, index);
436
437
if (!ALLOC_ARRAY(annotations->annotations, annotations->numberOfAnnotations, J9CfrAnnotation)) {
438
return BCT_ERR_OUT_OF_ROM;
439
}
440
441
result = readAnnotations(classfile, annotations->annotations, annotations->numberOfAnnotations, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags);
442
}
443
444
if (BCT_ERR_OUT_OF_ROM == result) {
445
/* Return out of memory error code to allocate larger buffer for classfile */
446
return result;
447
} else if ((BCT_ERR_NO_ERROR != result) || (0 == length) || (index != end)) {
448
U_32 cursor = 0;
449
Trc_BCU_MalformedAnnotation(address);
450
451
/* Capture the errors with type_name_index & const_name_index in enum_const_value against the VM Spec */
452
if (BCT_ERR_INVALID_ANNOTATION_BAD_CP_INDEX_OUT_OF_RANGE == result) {
453
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
454
offset = address;
455
goto _errorFound;
456
} else if (BCT_ERR_INVALID_ANNOTATION_BAD_CP_UTF8_STRING == result) {
457
errorCode = J9NLS_CFR_ERR_BAD_NAME_INDEX__ID;
458
offset = address;
459
goto _errorFound;
460
}
461
462
if (0 == length) {
463
/* rawDataLength should be zero to indicate an error. Add an extra byte to the annotation
464
* to indicate an error. This case will not be common. */
465
annotations->rawDataLength = 1;
466
if (!ALLOC_ARRAY(annotations->rawAttributeData, 1, U_8)) {
467
return BCT_ERR_OUT_OF_ROM;
468
}
469
annotations->rawAttributeData[0] = 0;
470
} else {
471
annotations->rawDataLength = length;
472
if (!ALLOC_ARRAY(annotations->rawAttributeData, length, U_8)) {
473
return BCT_ERR_OUT_OF_ROM;
474
}
475
index = attributeStart; /* rewind to the start of the attribute */
476
for (cursor = 0; cursor < annotations->rawDataLength; ++cursor) {
477
CHECK_EOF(1);
478
NEXT_U8(annotations->rawAttributeData[cursor], index);
479
}
480
}
481
}
482
}
483
break;
484
485
case CFR_ATTRIBUTE_MethodParameters:
486
if (!ALLOC_CAST(attrib, J9CfrAttributeMethodParameters, J9CfrAttribute)) {
487
return -2;
488
}
489
CHECK_EOF(1);
490
NEXT_U8(((J9CfrAttributeMethodParameters *) attrib)->numberOfMethodParameters, index);
491
492
if (!ALLOC_ARRAY(
493
((J9CfrAttributeMethodParameters *) attrib)->methodParametersIndexTable,
494
((J9CfrAttributeMethodParameters *) attrib)->numberOfMethodParameters,
495
U_16)) {
496
return -2;
497
}
498
499
if (!ALLOC_ARRAY(
500
((J9CfrAttributeMethodParameters *) attrib)->flags,
501
((J9CfrAttributeMethodParameters *) attrib)->numberOfMethodParameters,
502
U_16)) {
503
return -2;
504
}
505
506
/* We need 4 bytes for each methodParameter (2 for flags, 2 formethodParametersIndexTable ) */
507
CHECK_EOF(((J9CfrAttributeMethodParameters *) attrib)->numberOfMethodParameters * 4);
508
for (j = 0; j < ((J9CfrAttributeMethodParameters *) attrib)->numberOfMethodParameters; j++) {
509
NEXT_U16(((J9CfrAttributeMethodParameters *) attrib)->methodParametersIndexTable[j], index);
510
NEXT_U16(((J9CfrAttributeMethodParameters *) attrib)->flags[j], index);
511
}
512
break;
513
514
case CFR_ATTRIBUTE_RuntimeInvisibleParameterAnnotations:
515
if (invisibleParameterAnnotationsRead) {
516
/* found a redundant attribute */
517
errorCode = J9NLS_CFR_ERR_MULTIPLE_PARAMETER_ANNOTATION_ATTRIBUTES__ID;
518
offset = address;
519
goto _errorFound;
520
521
} else {
522
invisibleParameterAnnotationsRead = TRUE;
523
}
524
if (J9_ARE_NO_BITS_SET(flags, BCT_RetainRuntimeInvisibleAttributes)) {
525
if (!ALLOC(attrib, J9CfrAttribute)) { /* create dummy attribute and skip */
526
return -2;
527
}
528
CHECK_EOF(length);
529
index += length;
530
break;
531
} /* else FALLTHROUGH */
532
case CFR_ATTRIBUTE_RuntimeVisibleParameterAnnotations: {
533
U_8 *attributeStart = index;
534
J9CfrAttributeRuntimeVisibleParameterAnnotations *annotations = NULL;
535
if (CFR_ATTRIBUTE_RuntimeVisibleParameterAnnotations == tag) {
536
if (visibleParameterAnnotationsRead) {
537
/* found a redundant attribute */
538
errorCode = J9NLS_CFR_ERR_MULTIPLE_PARAMETER_ANNOTATION_ATTRIBUTES__ID;
539
offset = address;
540
goto _errorFound;
541
542
}
543
visibleParameterAnnotationsRead = TRUE;
544
}
545
if (!ALLOC_CAST(attrib, J9CfrAttributeRuntimeVisibleParameterAnnotations, J9CfrAttribute)) {
546
return -2;
547
}
548
annotations = (J9CfrAttributeRuntimeVisibleParameterAnnotations *)attrib;
549
annotations->rawAttributeData = NULL;
550
annotations->rawDataLength = 0; /* 0 indicates attribute is well-formed */
551
CHECK_EOF(1);
552
NEXT_U8(annotations->numberOfParameters, index);
553
554
if (!ALLOC_ARRAY(annotations->parameterAnnotations, annotations->numberOfParameters, J9CfrParameterAnnotations)) {
555
return -2;
556
}
557
558
parameterAnnotations = annotations->parameterAnnotations;
559
for (j = 0; j < annotations->numberOfParameters; j++, parameterAnnotations++) {
560
CHECK_EOF(2);
561
NEXT_U16(parameterAnnotations->numberOfAnnotations, index);
562
563
if (!ALLOC_ARRAY(parameterAnnotations->annotations, parameterAnnotations->numberOfAnnotations, J9CfrAnnotation)) {
564
return -2;
565
}
566
567
result = readAnnotations(classfile, parameterAnnotations->annotations, parameterAnnotations->numberOfAnnotations, data, dataEnd,
568
segment, segmentEnd, &index, &freePointer, flags);
569
570
if (BCT_ERR_NO_ERROR != result) {
571
break;
572
}
573
}
574
/* Jazz 104170: According to Java SE 8V M Spec at 4.7.18 The RuntimeVisibleParameterAnnotations Attribute:
575
* num_parameters == 0 means there is no parameter for this method and naturally no annotations
576
* for these parameters, in which case the code should treat this attribute as bad and ignore it.
577
*/
578
if (BCT_ERR_OUT_OF_ROM == result) {
579
/* Return out of memory error code to allocate larger buffer for classfile */
580
return result;
581
} else if ((BCT_ERR_NO_ERROR != result) || (index != end) || (0 == annotations->numberOfParameters)) {
582
U_32 cursor = 0;
583
/*
584
* give up parsing.
585
* Copy the raw data, a 0 where the num_parameters should be, followed by the rest of the data.
586
* This is forces an error because if num_parameters=0, there should be no more data in the attribute.
587
*/
588
Trc_BCU_MalformedParameterAnnotation(address);
589
if (!ALLOC_ARRAY(annotations->rawAttributeData, length + 1, U_8)) {
590
return -2;
591
}
592
index = attributeStart; /* rewind to the start of the attribute */
593
NEXT_U8(annotations->rawAttributeData[0], index); /* put in the num_parameters */
594
if (0 != annotations->rawAttributeData[0]) {
595
/* insert an error marker */
596
annotations->rawAttributeData[1] = annotations->rawAttributeData[0];
597
annotations->rawAttributeData[0] = 0;
598
annotations->rawDataLength = length + 1;
599
} else { /* the attribute is already marked bad */
600
if (length > 1) {
601
NEXT_U8(annotations->rawAttributeData[1], index);
602
}
603
annotations->rawDataLength = length;
604
}
605
606
/* Jazz 104170: Given that annotations->rawAttributeData[0] is set to 0
607
* in the case of malformed annotation attribute, we should also
608
* set num_parameters to 0 so as to skip this attribute when
609
* walking through attributes in ClassFileOracle::walkMethodAttributes().
610
*/
611
annotations->numberOfParameters = annotations->rawAttributeData[0];
612
613
for (cursor = 2; cursor < annotations->rawDataLength; ++cursor) {
614
CHECK_EOF(1);
615
NEXT_U8(annotations->rawAttributeData[cursor], index);
616
}
617
}
618
}
619
620
break;
621
622
case CFR_ATTRIBUTE_RuntimeInvisibleTypeAnnotations: {
623
if (invisibleTypeAttributeRead) {
624
/* found a second typeAnnotation attribute */
625
errorCode = J9NLS_CFR_ERR_MULTIPLE_TYPE_ANNOTATIONS_ATTRIBUTES__ID;
626
offset = address;
627
goto _errorFound;
628
}
629
invisibleTypeAttributeRead = TRUE;
630
if (J9_ARE_NO_BITS_SET(flags, BCT_RetainRuntimeInvisibleAttributes)) {
631
if (!ALLOC(attrib, J9CfrAttribute)) { /* create dummy attribute and skip */
632
return -2;
633
}
634
CHECK_EOF(length);
635
index += length;
636
break;
637
} /* else FALLTHROUGH */
638
}
639
case CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations: {
640
J9CfrAttributeRuntimeVisibleTypeAnnotations *annotations = NULL;
641
U_8 *attributeStart = index;
642
BOOLEAN foundError = FALSE;
643
{
644
if (CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations == tag) {
645
if (visibleTypeAttributeRead) {
646
/* found a second typeAnnotation attribute */
647
errorCode = J9NLS_CFR_ERR_MULTIPLE_TYPE_ANNOTATIONS_ATTRIBUTES__ID;
648
offset = address;
649
goto _errorFound;
650
}
651
visibleTypeAttributeRead = TRUE;
652
}
653
}
654
if (!ALLOC_CAST(attrib, J9CfrAttributeRuntimeVisibleTypeAnnotations, J9CfrAttribute)) {
655
return -2;
656
}
657
annotations = (J9CfrAttributeRuntimeVisibleTypeAnnotations *)attrib;
658
annotations->numberOfAnnotations = 0;
659
annotations->typeAnnotations = NULL;
660
annotations->rawAttributeData = NULL;
661
annotations->rawDataLength = 0; /* 0 indicates attribute is well-formed */
662
663
/* In the case of a malformed attribute numberOfAnnotations may not exist even if the file did not end.
664
* There must be at least two bytes to have a valid numberOfAnnotations.
665
* Length of 0 will be treated as an error below. Length of 1 will be an error as well since the index
666
* will not match the end value.
667
*/
668
if (length > 1) {
669
CHECK_EOF(2);
670
NEXT_U16(annotations->numberOfAnnotations, index);
671
672
if (!ALLOC_ARRAY(annotations->typeAnnotations, annotations->numberOfAnnotations, J9CfrTypeAnnotation)) {
673
return -2;
674
}
675
typeAnnotations = annotations->typeAnnotations;
676
/*
677
* we are now at the start of the first type_annotation
678
* Silently ignore errors.
679
*/
680
for (j = 0; j < annotations->numberOfAnnotations; j++, typeAnnotations++) {
681
result = readTypeAnnotation(classfile, typeAnnotations, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags);
682
if (BCT_ERR_NO_ERROR != result) {
683
break;
684
}
685
}
686
}
687
688
if (BCT_ERR_OUT_OF_ROM == result) {
689
/* Return out of memory error code to allocate larger buffer for classfile */
690
return result;
691
} else if ((BCT_ERR_NO_ERROR != result) || (0 == length) || (index != end)) {
692
/*
693
* Give up parsing.
694
*
695
* Copy the raw data, insert a bogus type_annotation,
696
* i.e. an illegal target_type byte immediately after the num_annotations field
697
* to indicate that the attribute is malformed. The remaining raw data should follow
698
* the illegal target_type.
699
*
700
* The minimum number of raw data bytes needed to create a bogus type_annotation is:
701
* num_annotations (2 bytes)
702
* target_type (1 byte)
703
* extra raw data (at least 1 byte)
704
*
705
* Length will be adjusted during rawAttributeData assignment if it is determined that
706
* an extra slot is not needed.
707
*/
708
const U_32 minimumRawDataBytes = 4;
709
710
Trc_BCU_MalformedTypeAnnotation(address);
711
712
annotations->rawDataLength = OMR_MAX(minimumRawDataBytes, length + 1);
713
714
if (!ALLOC_ARRAY(annotations->rawAttributeData, annotations->rawDataLength, U_8)) {
715
return -2;
716
}
717
index = attributeStart; /* rewind to the start of the attribute */
718
719
/* read num_annotations or set dummy if these bytes do not exist. */
720
if (length >= 2) {
721
NEXT_U16(annotations->rawAttributeData[0], index);
722
} else {
723
/* there should be at least one type_annotation here for the illegal
724
* entry that is being created. */
725
annotations->rawAttributeData[0] = 0;
726
annotations->rawAttributeData[1] = 1;
727
}
728
729
/* Insert illegal target_type followed by remaining raw data. */
730
if (index == end) {
731
/* There is no remaining raw data. */
732
annotations->rawAttributeData[2] = CFR_TARGET_TYPE_ErrorInAttribute;
733
734
/* Adjust rawDataLength since there was no need to insert an extra byte. */
735
annotations->rawDataLength -= 1;
736
} else {
737
/* cursor is the starting point in raw data array to write remaining raw data. */
738
U_32 cursor = 0;
739
740
NEXT_U8(annotations->rawAttributeData[2], index);
741
742
if (CFR_TARGET_TYPE_ErrorInAttribute != annotations->rawAttributeData[2]) {
743
/* insert an error marker */
744
annotations->rawAttributeData[3] = annotations->rawAttributeData[2];
745
annotations->rawAttributeData[2] = CFR_TARGET_TYPE_ErrorInAttribute;
746
cursor = 4;
747
} else {
748
/* The attribute is already marked bad.
749
* Adjust rawDataLength since there was no need to insert an extra byte.
750
*/
751
annotations->rawDataLength -= 1;
752
cursor = 3;
753
}
754
755
while (index != end) {
756
CHECK_EOF(1);
757
NEXT_U8(annotations->rawAttributeData[cursor], index);
758
cursor++;
759
}
760
}
761
}
762
763
result = 0;
764
}
765
break;
766
767
case CFR_ATTRIBUTE_InnerClasses:
768
if (!ALLOC(classes, J9CfrAttributeInnerClasses)) {
769
return -2;
770
}
771
attrib = (J9CfrAttribute*)classes;
772
CHECK_EOF(2);
773
NEXT_U16(classes->numberOfClasses, index);
774
if (!ALLOC_ARRAY(classes->classes, classes->numberOfClasses, J9CfrClassesEntry)) {
775
return -2;
776
}
777
CHECK_EOF(classes->numberOfClasses << 3);
778
for (j = 0; j < classes->numberOfClasses; j++) {
779
NEXT_U16(classes->classes[j].innerClassInfoIndex, index);
780
NEXT_U16(classes->classes[j].outerClassInfoIndex, index);
781
NEXT_U16(classes->classes[j].innerNameIndex, index);
782
NEXT_U16(classes->classes[j].innerClassAccessFlags, index);
783
}
784
break;
785
786
case CFR_ATTRIBUTE_BootstrapMethods:
787
if (bootstrapMethodAttributeRead) {
788
errorCode = J9NLS_CFR_ERR_FOUND_MULTIPLE_BOOTSTRAP_METHODS_ATTRIBUTES__ID;
789
offset = address;
790
goto _errorFound;
791
}
792
bootstrapMethodAttributeRead = TRUE;
793
if (!ALLOC(bootstrapMethods, J9CfrAttributeBootstrapMethods)) {
794
return -2;
795
}
796
attrib = (J9CfrAttribute*)bootstrapMethods;
797
CHECK_EOF(2);
798
NEXT_U16(bootstrapMethods->numberOfBootstrapMethods, index);
799
if (!ALLOC_ARRAY(bootstrapMethods->bootstrapMethods, bootstrapMethods->numberOfBootstrapMethods, J9CfrBootstrapMethod)) {
800
return -2;
801
}
802
for (j = 0; j < bootstrapMethods->numberOfBootstrapMethods; j++) {
803
CHECK_EOF(4);
804
NEXT_U16(bootstrapMethods->bootstrapMethods[j].bootstrapMethodIndex, index);
805
NEXT_U16(bootstrapMethods->bootstrapMethods[j].numberOfBootstrapArguments, index);
806
if (!ALLOC_ARRAY(bootstrapMethods->bootstrapMethods[j].bootstrapArguments, bootstrapMethods->bootstrapMethods[j].numberOfBootstrapArguments, U_16)) {
807
return -2;
808
}
809
CHECK_EOF(bootstrapMethods->bootstrapMethods[j].numberOfBootstrapArguments << 1);
810
for (k = 0; k < bootstrapMethods->bootstrapMethods[j].numberOfBootstrapArguments; k++) {
811
NEXT_U16(bootstrapMethods->bootstrapMethods[j].bootstrapArguments[k], index);
812
}
813
}
814
break;
815
816
case CFR_ATTRIBUTE_EnclosingMethod:
817
if (!ALLOC_CAST(attrib, J9CfrAttributeEnclosingMethod, J9CfrAttribute)) {
818
return -2;
819
}
820
CHECK_EOF(4);
821
NEXT_U16(((J9CfrAttributeEnclosingMethod *) attrib)->classIndex, index);
822
NEXT_U16(((J9CfrAttributeEnclosingMethod *) attrib)->methodIndex, index);
823
break;
824
825
case CFR_ATTRIBUTE_Deprecated:
826
if (!ALLOC_CAST(attrib, J9CfrAttributeDeprecated, J9CfrAttribute)) {
827
return -2;
828
}
829
CHECK_EOF(length);
830
index += length;
831
break;
832
833
case CFR_ATTRIBUTE_StackMapTable:
834
if (!ALLOC(stackMap, J9CfrAttributeStackMap)) {
835
return -2;
836
}
837
attrib = (J9CfrAttribute *)stackMap;
838
839
CHECK_EOF(2);
840
NEXT_U16(stackMap->numberOfEntries, index);
841
stackMap->mapLength = 0;
842
if (length > 1) {
843
stackMap->mapLength = length - 2;
844
}
845
846
if (!ALLOC_ARRAY(stackMap->entries, stackMap->mapLength, U_8)) {
847
return -2;
848
}
849
850
CHECK_EOF(stackMap->mapLength);
851
memcpy (stackMap->entries, index, stackMap->mapLength);
852
index += stackMap->mapLength;
853
854
break;
855
case CFR_ATTRIBUTE_Record:
856
/* JVMS 4.7.30: There may be at most one Record attribute in the attributes table of a ClassFile structure. */
857
if (recordAttributeRead){
858
errorCode = J9NLS_CFR_ERR_MULTIPLE_RECORD_ATTRIBUTES__ID;
859
offset = address;
860
goto _errorFound;
861
}
862
recordAttributeRead = TRUE;
863
864
/* set classfile flag for record class (used by cfdumper) */
865
classfile->j9Flags |= CFR_J9FLAG_IS_RECORD;
866
867
if (!ALLOC(record, J9CfrAttributeRecord)) {
868
return -2;
869
}
870
attrib = (J9CfrAttribute*)record;
871
872
CHECK_EOF(2);
873
NEXT_U16(record->numberOfRecordComponents, index);
874
875
if (!ALLOC_ARRAY(record->recordComponents, record->numberOfRecordComponents, J9CfrRecordComponent)) {
876
return -2;
877
}
878
for (j = 0; j < record->numberOfRecordComponents; j++) {
879
J9CfrRecordComponent* recordComponent = &(record->recordComponents[j]);
880
CHECK_EOF(6);
881
NEXT_U16(recordComponent->nameIndex, index);
882
NEXT_U16(recordComponent->descriptorIndex, index);
883
NEXT_U16(recordComponent->attributesCount, index);
884
if (!ALLOC_ARRAY(recordComponent->attributes, recordComponent->attributesCount, J9CfrAttribute *)) {
885
return -2;
886
}
887
result = readAttributes(classfile, &(recordComponent->attributes), recordComponent->attributesCount, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags, NULL);
888
if (result != 0) {
889
return result;
890
}
891
}
892
break;
893
case CFR_ATTRIBUTE_PermittedSubclasses:
894
/* JVMS: There may be at most one PermittedSubclasses attribute in the attributes table of a ClassFile structure... */
895
if (permittedSubclassesAttributeRead) {
896
errorCode = J9NLS_CFR_ERR_MULTIPLE_PERMITTEDSUBCLASSES_ATTRIBUTES__ID;
897
offset = address;
898
goto _errorFound;
899
}
900
permittedSubclassesAttributeRead = TRUE;
901
902
/* set classfile flag for sealed class (used by cfdumper) */
903
classfile->j9Flags |= CFR_J9FLAG_IS_SEALED;
904
905
if (!ALLOC(permittedSubclasses, J9CfrAttributePermittedSubclasses)) {
906
return -2;
907
}
908
attrib = (J9CfrAttribute*)permittedSubclasses;
909
910
CHECK_EOF(2);
911
NEXT_U16(permittedSubclasses->numberOfClasses, index);
912
913
if (!ALLOC_ARRAY(permittedSubclasses->classes, permittedSubclasses->numberOfClasses, U_16)) {
914
return -2;
915
}
916
for (j = 0; j < permittedSubclasses->numberOfClasses; j++) {
917
CHECK_EOF(2);
918
NEXT_U16(permittedSubclasses->classes[j], index);
919
}
920
break;
921
922
#if JAVA_SPEC_VERSION >= 11
923
case CFR_ATTRIBUTE_NestHost:
924
if (nestAttributeRead) {
925
errorCode = J9NLS_CFR_ERR_MULTIPLE_NEST_ATTRIBUTES__ID;
926
offset = address;
927
goto _errorFound;
928
}
929
930
if (!ALLOC(nestHost, J9CfrAttributeNestHost)) {
931
return -2;
932
}
933
nestAttributeRead = TRUE;
934
attrib = (J9CfrAttribute*)nestHost;
935
936
CHECK_EOF(2);
937
NEXT_U16(nestHost->hostClassIndex, index);
938
break;
939
940
case CFR_ATTRIBUTE_NestMembers: {
941
U_16 numberOfClasses;
942
if (nestAttributeRead) {
943
errorCode = J9NLS_CFR_ERR_MULTIPLE_NEST_ATTRIBUTES__ID;
944
offset = address;
945
goto _errorFound;
946
}
947
948
if (!ALLOC(nestMembers, J9CfrAttributeNestMembers)) {
949
return -2;
950
}
951
nestAttributeRead = TRUE;
952
attrib = (J9CfrAttribute*)nestMembers;
953
954
CHECK_EOF(2);
955
NEXT_U16(numberOfClasses, index);
956
nestMembers->numberOfClasses = numberOfClasses;
957
958
if (!ALLOC_ARRAY(nestMembers->classes, numberOfClasses, U_16)) {
959
return -2;
960
}
961
962
CHECK_EOF(2 * numberOfClasses);
963
964
for (j = 0; j < numberOfClasses; j++) {
965
NEXT_U16(nestMembers->classes[j], index);
966
}
967
break;
968
}
969
#endif /* JAVA_SPEC_VERSION >= 11 */
970
971
case CFR_ATTRIBUTE_StrippedLineNumberTable:
972
case CFR_ATTRIBUTE_StrippedLocalVariableTable:
973
case CFR_ATTRIBUTE_StrippedLocalVariableTypeTable:
974
case CFR_ATTRIBUTE_StrippedInnerClasses:
975
case CFR_ATTRIBUTE_StrippedSourceDebugExtension:
976
case CFR_ATTRIBUTE_StrippedUnknown:
977
if (!ALLOC(attrib, J9CfrAttribute)) {
978
return -2;
979
}
980
CHECK_EOF(length);
981
index += length;
982
break;
983
984
case CFR_ATTRIBUTE_SourceDebugExtension:
985
if (sourceDebugExtensionRead) {
986
/* found a redundant attribute */
987
errorCode = J9NLS_CFR_ERR_MULTIPLE_SOURCE_DEBUG_EXTENSION_ATTRIBUTES__ID;
988
offset = address;
989
goto _errorFound;
990
991
} else {
992
sourceDebugExtensionRead = TRUE;
993
}
994
/* FALLTHROUGH */
995
case CFR_ATTRIBUTE_StackMap: /* CLDC StackMap - Not supported in J2SE */
996
case CFR_ATTRIBUTE_Unknown:
997
default:
998
if (!ALLOC_CAST(attrib, J9CfrAttributeUnknown, J9CfrAttribute)) {
999
return -2;
1000
}
1001
if (!ALLOC_ARRAY(((J9CfrAttributeUnknown*) attrib)->value, length, U_8)) {
1002
return -2;
1003
}
1004
CHECK_EOF(length);
1005
memcpy (((J9CfrAttributeUnknown *) attrib)->value, index, length);
1006
index += length;
1007
break;
1008
}
1009
1010
attrib->tag = tag;
1011
attrib->nameIndex = (U_16) name;
1012
attrib->length = length;
1013
attrib->romAddress = address;
1014
attributes[i] = (J9CfrAttribute *) attrib;
1015
1016
if (index != end) {
1017
errorCode = (U_32) ((index < end) ? J9NLS_CFR_ERR_LENGTH_TOO_SMALL__ID : J9NLS_CFR_ERR_LENGTH_TOO_BIG__ID);
1018
offset = address + 2;
1019
goto _errorFound;
1020
}
1021
}
1022
1023
*pAttributes = attributes;
1024
*pIndex = index;
1025
*pFreePointer = freePointer;
1026
return 0;
1027
1028
_errorFound:
1029
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, offset);
1030
return -1;
1031
}
1032
1033
1034
1035
/*
1036
Read the methods from the bytes in @data.
1037
Returns 0 on success, non-zero on failure.
1038
*/
1039
1040
static I_32
1041
readMethods(J9CfrClassFile* classfile, U_8* data, U_8* dataEnd, U_8* segment, U_8* segmentEnd, U_8** pIndex, U_8** pFreePointer, U_32 flags)
1042
{
1043
U_8* index = *pIndex;
1044
U_8* freePointer = *pFreePointer;
1045
J9CfrMethod* method;
1046
UDATA errorCode, offset;
1047
U_32 i;
1048
I_32 result;
1049
1050
for (i = 0; i < classfile->methodsCount; i++) {
1051
U_32 j;
1052
UDATA syntheticFound = FALSE;
1053
1054
method = &(classfile->methods[i]);
1055
method->romAddress = (UDATA) (index - data);
1056
1057
CHECK_EOF(8);
1058
method->accessFlags = NEXT_U16(method->accessFlags, index) & CFR_METHOD_ACCESS_MASK;
1059
method->j9Flags = 0;
1060
NEXT_U16(method->nameIndex, index);
1061
NEXT_U16(method->descriptorIndex, index);
1062
NEXT_U16(method->attributesCount, index);
1063
1064
if (!ALLOC_ARRAY(method->attributes, method->attributesCount, J9CfrAttribute*)) {
1065
return -2;
1066
}
1067
1068
/* Read the attributes. */
1069
if ((result = readAttributes(classfile, &(method->attributes), method->attributesCount, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags, &syntheticFound))!= 0) {
1070
return result;
1071
}
1072
if (syntheticFound) {
1073
method->accessFlags |= CFR_ACC_SYNTHETIC;
1074
}
1075
1076
method->codeAttribute = NULL;
1077
method->exceptionsAttribute = NULL;
1078
method->methodParametersAttribute = NULL;
1079
for (j = 0; j < method->attributesCount; j++) {
1080
switch (method->attributes[j]->tag) {
1081
case CFR_ATTRIBUTE_Code:
1082
if (method->codeAttribute) {
1083
/* found a second one! */
1084
errorCode = J9NLS_CFR_ERR_TWO_CODE_ATTRIBUTES__ID;
1085
offset = method->attributes[j]->romAddress;
1086
goto _errorFound;
1087
}
1088
method->codeAttribute = (J9CfrAttributeCode*)(method->attributes[j]);
1089
break;
1090
case CFR_ATTRIBUTE_Exceptions:
1091
if (method->exceptionsAttribute) {
1092
/* found a second one! */
1093
errorCode = J9NLS_CFR_ERR_TWO_EXCEPTIONS_ATTRIBUTES__ID;
1094
offset = method->attributes[j]->romAddress;
1095
goto _errorFound;
1096
}
1097
method->exceptionsAttribute = (J9CfrAttributeExceptions*)(method->attributes[j]);
1098
break;
1099
case CFR_ATTRIBUTE_MethodParameters:
1100
if (method->methodParametersAttribute) {
1101
/* found a second one! */
1102
errorCode = J9NLS_CFR_ERR_TWO_METHOD_PARAMETERS_ATTRIBUTES__ID;
1103
offset = method->attributes[j]->romAddress;
1104
goto _errorFound;
1105
}
1106
method->methodParametersAttribute = (J9CfrAttributeMethodParameters*)(method->attributes[j]);
1107
}
1108
}
1109
}
1110
1111
*pIndex = index;
1112
*pFreePointer = freePointer;
1113
return 0;
1114
1115
_errorFound:
1116
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, offset);
1117
return -1;
1118
}
1119
1120
1121
/*
1122
Read the methods from the bytes in @data.
1123
Returns 0 on success, non-zero on failure.
1124
*/
1125
1126
static I_32
1127
readFields(J9CfrClassFile* classfile, U_8* data, U_8* dataEnd, U_8* segment, U_8* segmentEnd, U_8** pIndex, U_8** pFreePointer, U_32 flags)
1128
{
1129
U_8* index = *pIndex;
1130
U_8* freePointer = *pFreePointer;
1131
J9CfrField* field;
1132
UDATA errorCode, offset;
1133
U_32 i, j;
1134
I_32 result;
1135
1136
field = classfile->fields;
1137
for (i = 0; i < classfile->fieldsCount; i++, field++) {
1138
UDATA syntheticFound = FALSE;
1139
1140
field->romAddress = (UDATA) (index - data);
1141
1142
CHECK_EOF(8);
1143
field->accessFlags = NEXT_U16(field->accessFlags, index) & CFR_FIELD_ACCESS_MASK;
1144
NEXT_U16(field->nameIndex, index);
1145
NEXT_U16(field->descriptorIndex, index);
1146
NEXT_U16(field->attributesCount, index);
1147
1148
if (!ALLOC_ARRAY(field->attributes, field->attributesCount, J9CfrAttribute*)) {
1149
return -2;
1150
}
1151
1152
/* Read the attributes. */
1153
if ((result = readAttributes(classfile, &(field->attributes), field->attributesCount, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags, &syntheticFound)) != 0) {
1154
return result;
1155
}
1156
if (syntheticFound) {
1157
field->accessFlags |= CFR_ACC_SYNTHETIC;
1158
}
1159
1160
field->constantValueAttribute = NULL;
1161
for (j = 0; j < field->attributesCount; j++) {
1162
if (field->attributes[j]->tag == CFR_ATTRIBUTE_ConstantValue) {
1163
if (field->constantValueAttribute) {
1164
/* found a second one! */
1165
errorCode = J9NLS_CFR_ERR_TWO_CONSTANT_VALUE_ATTRIBUTES__ID;
1166
offset = field->attributes[j]->romAddress;
1167
goto _errorFound;
1168
}
1169
field->constantValueAttribute = (J9CfrAttributeConstantValue*)(field->attributes[j]);
1170
}
1171
}
1172
}
1173
1174
*pIndex = index;
1175
*pFreePointer = freePointer;
1176
return 0;
1177
1178
_errorFound:
1179
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, offset);
1180
return -1;
1181
}
1182
1183
1184
/*
1185
Read the constant pool from the bytes in @data.
1186
Returns 0 on success, non-zero on failure.
1187
*/
1188
1189
static I_32
1190
readPool(J9CfrClassFile* classfile, U_8* data, U_8* dataEnd, U_8* segment, U_8* segmentEnd, U_8** pIndex, U_8** pFreePointer)
1191
{
1192
U_8* index = *pIndex;
1193
U_8* freePointer = *pFreePointer;
1194
J9CfrConstantPoolInfo* info;
1195
J9CfrConstantPoolInfo* previousUTF8;
1196
J9CfrConstantPoolInfo* previousNAT;
1197
U_32 size, errorCode, offset;
1198
U_32 i;
1199
I_32 verifyResult;
1200
1201
/* Explicitly zero the null entry */
1202
info = &(classfile->constantPool[0]);
1203
info->tag = CFR_CONSTANT_Null;
1204
info->flags1 = 0;
1205
info->nextCPIndex = 0;
1206
info->slot1 = 0;
1207
info->slot2 = 0;
1208
info->bytes = 0;
1209
info->romAddress = 0;
1210
classfile->firstUTF8CPIndex = 0;
1211
classfile->firstNATCPIndex = 0;
1212
1213
/* Read each entry. */
1214
for (i = 1; i < classfile->constantPoolCount;) {
1215
info = &(classfile->constantPool[i]);
1216
CHECK_EOF(1);
1217
NEXT_U8(info->tag, index);
1218
info->flags1 = 0;
1219
info->nextCPIndex = 0;
1220
info->romAddress = 0;
1221
switch (info->tag) {
1222
case CFR_CONSTANT_Utf8:
1223
CHECK_EOF(2);
1224
NEXT_U16(size, index);
1225
info->slot2 = 0;
1226
1227
if (!ALLOC_ARRAY(info->bytes, size + 1, U_8)) {
1228
return -2;
1229
}
1230
CHECK_EOF(size);
1231
verifyResult = j9bcutil_verifyCanonisizeAndCopyUTF8(info->bytes, index, size, &(info->flags1));
1232
info->slot1 = (U_32) verifyResult;
1233
if ((verifyResult < 0) ||
1234
(J9_ARE_ALL_BITS_SET(info->flags1, CFR_FOUND_CHARS_IN_EXTENDED_MUE_FORM) && (classfile->majorVersion >= 48))
1235
) {
1236
errorCode = J9NLS_CFR_ERR_BAD_UTF8__ID;
1237
offset = (U_32) (index - data - 1);
1238
goto _errorFound;
1239
}
1240
info->bytes[info->slot1] = (U_8) '\0';
1241
/* correct for compression */
1242
freePointer -= (size - info->slot1);
1243
index += size;
1244
if (0 == classfile->firstUTF8CPIndex) {
1245
classfile->firstUTF8CPIndex = i;
1246
previousUTF8 = info;
1247
} else {
1248
previousUTF8->nextCPIndex = (U_16)i;
1249
previousUTF8 = info;
1250
}
1251
classfile->lastUTF8CPIndex = i;
1252
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1253
/**
1254
* The following line should be put inside if (classfile->majorVersion > 61) according to the SPEC. However, the current
1255
* OpenJDK Valhalla implementation is not updated on this yet. There are cases that the new VT form is used in old classes
1256
* from OpenJDK Valhalla JCL.
1257
*/
1258
info->flags1 |= CFR_CLASS_FILE_VERSION_SUPPORT_VALUE_TYPE;
1259
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
1260
i++;
1261
break;
1262
1263
case CFR_CONSTANT_Integer:
1264
case CFR_CONSTANT_Float:
1265
CHECK_EOF(4);
1266
NEXT_U32(info->slot1, index);
1267
info->slot2 = 0;
1268
i++;
1269
break;
1270
1271
case CFR_CONSTANT_Long:
1272
case CFR_CONSTANT_Double:
1273
CHECK_EOF(8);
1274
#ifdef J9VM_ENV_LITTLE_ENDIAN
1275
NEXT_U32(info->slot2, index);
1276
NEXT_U32(info->slot1, index);
1277
#else
1278
NEXT_U32(info->slot1, index);
1279
NEXT_U32(info->slot2, index);
1280
#endif
1281
i++;
1282
classfile->constantPool[i].tag = CFR_CONSTANT_Null;
1283
i++;
1284
if (i > classfile->constantPoolCount) {
1285
/* Incomplete long or double constant. This means that n+1 is out of range. */
1286
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1287
offset = (U_32) (index - data - 1);
1288
goto _errorFound;
1289
}
1290
break;
1291
1292
case CFR_CONSTANT_MethodType:
1293
if (classfile->majorVersion < 51) {
1294
errorCode = J9NLS_CFR_ERR_CP_ENTRY_INVALID_BEFORE_V51__ID;
1295
offset = (U_32) (index - data - 1);
1296
goto _errorFound;
1297
}
1298
case CFR_CONSTANT_Class:
1299
case CFR_CONSTANT_String:
1300
CHECK_EOF(2);
1301
NEXT_U16(info->slot1, index);
1302
info->slot2 = 0;
1303
i++;
1304
break;
1305
1306
case CFR_CONSTANT_Dynamic:
1307
if (classfile->majorVersion < 55) {
1308
errorCode = J9NLS_CFR_ERR_CP_ENTRY_INVALID_BEFORE_V55__ID;
1309
offset = (U_32) (index - data - 1);
1310
goto _errorFound;
1311
}
1312
/* fall through */
1313
case CFR_CONSTANT_InvokeDynamic:
1314
if (classfile->majorVersion < 51) {
1315
errorCode = J9NLS_CFR_ERR_CP_ENTRY_INVALID_BEFORE_V51__ID;
1316
offset = (U_32) (index - data - 1);
1317
goto _errorFound;
1318
}
1319
/* fall through */
1320
case CFR_CONSTANT_Fieldref:
1321
case CFR_CONSTANT_Methodref:
1322
case CFR_CONSTANT_InterfaceMethodref:
1323
CHECK_EOF(4);
1324
NEXT_U16(info->slot1, index);
1325
NEXT_U16(info->slot2, index);
1326
i++;
1327
break;
1328
1329
case CFR_CONSTANT_NameAndType:
1330
CHECK_EOF(4);
1331
NEXT_U16(info->slot1, index);
1332
NEXT_U16(info->slot2, index);
1333
if (0 == classfile->firstNATCPIndex) {
1334
classfile->firstNATCPIndex = i;
1335
previousNAT = info;
1336
} else {
1337
previousNAT->nextCPIndex = (U_16)i;
1338
previousNAT = info;
1339
}
1340
i++;
1341
break;
1342
1343
case CFR_CONSTANT_MethodHandle:
1344
if (classfile->majorVersion < 51) {
1345
errorCode = J9NLS_CFR_ERR_CP_ENTRY_INVALID_BEFORE_V51__ID;
1346
offset = (U_32) (index - data - 1);
1347
goto _errorFound;
1348
}
1349
CHECK_EOF(3);
1350
NEXT_U8(info->slot1, index);
1351
NEXT_U16(info->slot2, index);
1352
i++;
1353
break;
1354
1355
case CFR_CONSTANT_Module:
1356
case CFR_CONSTANT_Package:
1357
if (classfile->majorVersion < 53) {
1358
errorCode = J9NLS_CFR_ERR_CP_ENTRY_INVALID_BEFORE_V53__ID;
1359
offset = (U_32)(index - data - 1);
1360
goto _errorFound;
1361
}
1362
CHECK_EOF(2);
1363
NEXT_U16(info->slot1, index);
1364
i++;
1365
break;
1366
1367
default:
1368
errorCode = J9NLS_CFR_ERR_UNKNOWN_CONSTANT__ID;
1369
offset = (U_32) (index - data - 1);
1370
goto _errorFound;
1371
}
1372
}
1373
*pIndex = index;
1374
*pFreePointer = freePointer;
1375
return 0;
1376
1377
_errorFound:
1378
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, offset);
1379
return -1;
1380
}
1381
1382
1383
/*
1384
Check the validity of the constant pool.
1385
@param maxBootstrapMethodIndex (out) Pass back the largest bootstrap table index used by invokeDynamic
1386
@return 0 on success, non-zero on failure.
1387
*/
1388
1389
static I_32
1390
checkPool(J9CfrClassFile* classfile, U_8* segment, U_8* poolStart, I_32 *maxBootstrapMethodIndex, U_32 flags)
1391
{
1392
J9CfrConstantPoolInfo* info;
1393
J9CfrConstantPoolInfo* utf8;
1394
J9CfrConstantPoolInfo* cpBase;
1395
U_32 count, i, errorCode;
1396
U_8* index;
1397
1398
cpBase = classfile->constantPool;
1399
count = classfile->constantPoolCount;
1400
index = poolStart;
1401
1402
info = &cpBase[1];
1403
1404
for (i = 1; i < count; i++, info++) {
1405
1406
switch (info->tag) {
1407
1408
case CFR_CONSTANT_Utf8:
1409
/* Check format? */
1410
index += info->slot1 + 3;
1411
break;
1412
1413
case CFR_CONSTANT_Integer:
1414
case CFR_CONSTANT_Float:
1415
index += 5;
1416
break;
1417
1418
case CFR_CONSTANT_Long:
1419
case CFR_CONSTANT_Double:
1420
index += 9;
1421
i++;
1422
info++;
1423
break;
1424
1425
case CFR_CONSTANT_Class:
1426
/* Must be a UTF8. */
1427
if ((!(info->slot1)) || (info->slot1 > count)) {
1428
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1429
goto _errorFound;
1430
}
1431
1432
utf8 = &cpBase[info->slot1];
1433
if (utf8->tag != CFR_CONSTANT_Utf8) {
1434
errorCode = J9NLS_CFR_ERR_BAD_NAME_INDEX__ID;
1435
goto _errorFound;
1436
}
1437
1438
index += 3;
1439
break;
1440
1441
case CFR_CONSTANT_String:
1442
/* Must be a UTF8. */
1443
if ((!(info->slot1)) || (info->slot1 > count)) {
1444
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1445
goto _errorFound;
1446
}
1447
if (cpBase[info->slot1].tag != CFR_CONSTANT_Utf8) {
1448
errorCode = J9NLS_CFR_ERR_BAD_STRING_INDEX__ID;
1449
goto _errorFound;
1450
}
1451
index += 3;
1452
break;
1453
1454
case CFR_CONSTANT_Fieldref:
1455
case CFR_CONSTANT_Methodref:
1456
case CFR_CONSTANT_InterfaceMethodref:
1457
if (!(info->slot1) || (info->slot1 > count)) {
1458
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1459
goto _errorFound;
1460
}
1461
if (cpBase[info->slot1].tag != CFR_CONSTANT_Class) {
1462
errorCode = J9NLS_CFR_ERR_BAD_CLASS_INDEX__ID;
1463
goto _errorFound;
1464
}
1465
1466
if (!(info->slot2) || (info->slot2 > count)) {
1467
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1468
goto _errorFound;
1469
}
1470
if (cpBase[info->slot2].tag != CFR_CONSTANT_NameAndType) {
1471
errorCode = J9NLS_CFR_ERR_BAD_NAME_AND_TYPE_INDEX__ID;
1472
goto _errorFound;
1473
}
1474
index += 5;
1475
break;
1476
1477
case CFR_CONSTANT_NameAndType:
1478
if ((!(info->slot1)) || (info->slot1 > count)) {
1479
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1480
goto _errorFound;
1481
}
1482
if (cpBase[info->slot1].tag != CFR_CONSTANT_Utf8) {
1483
errorCode = J9NLS_CFR_ERR_BAD_NAME_INDEX__ID;
1484
goto _errorFound;
1485
}
1486
1487
if ((!(info->slot2)) || (info->slot2 > count)) {
1488
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1489
goto _errorFound;
1490
}
1491
if (cpBase[info->slot2].tag != CFR_CONSTANT_Utf8) {
1492
errorCode = J9NLS_CFR_ERR_BAD_DESCRIPTOR_INDEX__ID;
1493
goto _errorFound;
1494
}
1495
index += 5;
1496
break;
1497
1498
1499
case CFR_CONSTANT_MethodType:
1500
if (!(info->slot1) || (info->slot1 > count)) {
1501
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1502
goto _errorFound;
1503
}
1504
if (cpBase[info->slot1].tag != CFR_CONSTANT_Utf8) {
1505
errorCode = J9NLS_CFR_ERR_BAD_DESCRIPTOR_INDEX__ID;
1506
goto _errorFound;
1507
}
1508
index += 3;
1509
break;
1510
1511
case CFR_CONSTANT_MethodHandle:
1512
/* Format requires that slot1 is between
1513
* 1 and 9 and that slot2 is either a field
1514
* or method ref or interface method ref.
1515
* Checking for the correct 'kind' (slot1) occurs
1516
* in the check for the correct 'ref' (slot2).
1517
*/
1518
1519
/* Ensure the ref field is a valid cpEntry index */
1520
if (!(info->slot2) || (info->slot2 > count)) {
1521
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1522
goto _errorFound;
1523
}
1524
/* Must be either FieldRef or MethodRef or InterfaceMethodRef */
1525
switch(cpBase[info->slot2].tag){
1526
case CFR_CONSTANT_Fieldref:
1527
/* Kinds 1 - 4 must reference fields */
1528
if ((info->slot1 < 1) || (info->slot1 > 4)) {
1529
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1530
goto _errorFound;
1531
}
1532
break;
1533
case CFR_CONSTANT_Methodref:
1534
/* Kinds 5 - 8 must reference methodrefs */
1535
if ((info->slot1 < MH_REF_INVOKEVIRTUAL) || (info->slot1 > MH_REF_NEWINVOKESPECIAL)) {
1536
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1537
goto _errorFound;
1538
}
1539
break;
1540
case CFR_CONSTANT_InterfaceMethodref:
1541
/* Kind 9 must reference interface methodrefs.
1542
* If major version >= 52.0, Kind 6 and 7 can also reference interface methodrefs.
1543
*/
1544
if ((info->slot1 != MH_REF_INVOKEINTERFACE)
1545
&& (!((classfile->majorVersion >= 52)
1546
&& ((info->slot1 == MH_REF_INVOKESTATIC) || (info->slot1 == MH_REF_INVOKESPECIAL))))
1547
) {
1548
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1549
goto _errorFound;
1550
}
1551
break;
1552
default:
1553
errorCode = J9NLS_CFR_ERR_BAD_METHODHANDLE_REF_INDEX__ID;
1554
goto _errorFound;
1555
}
1556
1557
index += 4;
1558
break;
1559
1560
case CFR_CONSTANT_Dynamic: /* fall through */
1561
case CFR_CONSTANT_InvokeDynamic:
1562
/* Slot1 is an index into the BootstrapMethods_attribute - can't be validated yet */
1563
if (((I_32) info->slot1) > *maxBootstrapMethodIndex) {
1564
*maxBootstrapMethodIndex = info->slot1;
1565
}
1566
1567
/* Slot2 is a NAS */
1568
if (!(info->slot2) || (info->slot2 > count)) {
1569
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1570
goto _errorFound;
1571
}
1572
if (cpBase[info->slot2].tag != CFR_CONSTANT_NameAndType) {
1573
errorCode = J9NLS_CFR_ERR_BAD_NAME_AND_TYPE_INDEX__ID;
1574
goto _errorFound;
1575
}
1576
index += 5;
1577
break;
1578
1579
/* According to the VM Spec, a CONSTANT_Module_info or CONSTANT_Package_info structure
1580
* is permitted only in the constant pool of a class file where the access_flags item
1581
* has the ACC_MODULE flag set, which means any other class with a CONSTANT_Module_info
1582
* or CONSTANT_Package_info structure is illegal.
1583
* Note: a class with ACC_MODULE set is checked and rejected in j9bcutil_readClassFileBytes()
1584
* prior to checkPool().
1585
*/
1586
case CFR_CONSTANT_Module:
1587
errorCode = J9NLS_CFR_ERR_CONSTANT_MODULE_OUTSIDE_MODULE__ID;
1588
goto _errorFound;
1589
1590
case CFR_CONSTANT_Package:
1591
errorCode = J9NLS_CFR_ERR_CONSTANT_PACKAGE_OUTSIDE_MODULE__ID;
1592
goto _errorFound;
1593
1594
default:
1595
errorCode = J9NLS_CFR_ERR_UNKNOWN_CONSTANT__ID;
1596
goto _errorFound;
1597
}
1598
}
1599
1600
return 0;
1601
1602
_errorFound:
1603
1604
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, (UDATA) (index - poolStart + 10));
1605
return -1;
1606
}
1607
1608
/*
1609
Verify (pass 1) the fields in @classfile.
1610
Returns 0 on success, non-zero on failure.
1611
*/
1612
static I_32
1613
checkFields(J9PortLibrary* portLib, J9CfrClassFile * classfile, U_8 * segment, U_32 flags)
1614
{
1615
J9CfrField *field;
1616
U_32 value, maskedValue, errorCode, offset = 0;
1617
U_32 i;
1618
U_8 sigChar, sigTag, constantTag;
1619
1620
for (i = 0; i < classfile->fieldsCount; i++) {
1621
field = &(classfile->fields[i]);
1622
value = field->accessFlags & CFR_FIELD_ACCESS_MASK;
1623
1624
if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(5)) {
1625
value &= ~CFR_FIELD_ACCESS_NEWJDK5_MASK;
1626
}
1627
1628
1629
if (classfile->accessFlags & CFR_ACC_INTERFACE) {
1630
/* check that there are no flags set that are not allowed AND the required flags are set */
1631
if ((value & ~CFR_INTERFACE_FIELD_ACCESS_MASK) ||
1632
((value & CFR_INTERFACE_FIELD_ACCESS_REQUIRED) != CFR_INTERFACE_FIELD_ACCESS_REQUIRED)) {
1633
errorCode = J9NLS_CFR_ERR_INTERFACE_FIELD__ID;
1634
goto _errorFound;
1635
}
1636
}
1637
1638
maskedValue = value & CFR_PUBLIC_PRIVATE_PROTECTED_MASK;
1639
/* Check none or only one of the access flags set - result is 0 if no bits or only 1 bit is set */
1640
if (maskedValue & (maskedValue - 1)) {
1641
errorCode = J9NLS_CFR_ERR_ACCESS_CONFLICT_FIELD__ID;
1642
goto _errorFound;
1643
}
1644
1645
if ((value & (U_32) (CFR_ACC_FINAL | CFR_ACC_VOLATILE)) == (U_32) (CFR_ACC_FINAL | CFR_ACC_VOLATILE)) {
1646
errorCode = J9NLS_CFR_ERR_FINAL_VOLATILE_FIELD__ID;
1647
goto _errorFound;
1648
}
1649
1650
offset = 2;
1651
value = field->nameIndex;
1652
if ((!value) || (value >= classfile->constantPoolCount)) {
1653
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1654
goto _errorFound;
1655
}
1656
if (classfile->constantPool[value].tag != CFR_CONSTANT_Utf8) {
1657
errorCode = J9NLS_CFR_ERR_BAD_NAME_INDEX__ID;
1658
goto _errorFound;
1659
}
1660
/* field names are checked for well-formedness by the static verifier */
1661
1662
offset = 4;
1663
value = field->descriptorIndex;
1664
if ((!value) || (value >= classfile->constantPoolCount)) {
1665
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1666
goto _errorFound;
1667
}
1668
if (classfile->constantPool[value].tag != CFR_CONSTANT_Utf8) {
1669
errorCode = J9NLS_CFR_ERR_BAD_DESCRIPTOR_INDEX__ID;
1670
goto _errorFound;
1671
}
1672
/* field signature checked in j9bcv_verifyClassStructure */
1673
1674
/* Check the attributes. */
1675
if (checkAttributes(portLib, classfile, field->attributes, field->attributesCount, segment, -1, OUTSIDE_CODE, flags)) {
1676
return -1;
1677
}
1678
1679
/* Ensure that the constantValueAttribute is appropriate. */
1680
if (field->constantValueAttribute && (field->accessFlags & CFR_ACC_FINAL) &&
1681
(field->accessFlags & CFR_ACC_STATIC)) {
1682
sigChar = classfile->constantPool[field->descriptorIndex].bytes[0];
1683
constantTag = classfile->constantPool[field->constantValueAttribute->constantValueIndex].tag;
1684
if ((sigChar < 'A') || (sigChar > 'Z')) {
1685
errorCode = J9NLS_CFR_ERR_INCOMPATIBLE_CONSTANT__ID;
1686
goto _errorFound;
1687
}
1688
sigTag = (U_32) cpTypeCharConversion[sigChar - 'A'];
1689
if (sigTag == constantTag) {
1690
if (sigTag == CFR_CONSTANT_String) {
1691
/* Reject a String ConstantValue for anything but java.lang.String. */
1692
if (!utf8Equal(&classfile->constantPool[field->descriptorIndex], "Ljava/lang/String;", 18)) {
1693
errorCode = J9NLS_CFR_ERR_INCOMPATIBLE_CONSTANT__ID;
1694
goto _errorFound;
1695
}
1696
}
1697
} else {
1698
errorCode = J9NLS_CFR_ERR_INCOMPATIBLE_CONSTANT__ID;
1699
goto _errorFound;
1700
}
1701
}
1702
}
1703
1704
return 0;
1705
1706
_errorFound:
1707
1708
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, field->romAddress + offset);
1709
return -1;
1710
}
1711
1712
1713
1714
/*
1715
Check the methods in @classfile.
1716
Returns 0 on success, non-zero on failure.
1717
*/
1718
1719
static I_32
1720
checkMethods(J9PortLibrary* portLib, J9CfrClassFile* classfile, U_8* segment, U_32 vmVersionShifted, U_32 flags)
1721
{
1722
J9CfrMethod* method;
1723
U_32 value = 0;
1724
U_32 maskedValue = 0;
1725
U_32 errorCode = 0;
1726
U_32 offset = 0;
1727
U_32 i;
1728
BOOLEAN nameIndexOK;
1729
U_32 classfileVersion = flags & BCT_MajorClassFileVersionMask;
1730
1731
for (i = 0; i < classfile->methodsCount; i++) {
1732
method = &(classfile->methods[i]);
1733
1734
/* Can we trust the name index? */
1735
nameIndexOK = TRUE;
1736
value = method->nameIndex;
1737
if ((!value) || (value >= classfile->constantPoolCount)) {
1738
nameIndexOK = FALSE;
1739
} else if (classfile->constantPool[value].tag != CFR_CONSTANT_Utf8) {
1740
nameIndexOK = FALSE;
1741
}
1742
1743
value = method->accessFlags & CFR_METHOD_ACCESS_MASK;
1744
1745
if (classfileVersion < BCT_JavaMajorVersionShifted(5)) {
1746
value &= ~CFR_METHOD_ACCESS_NEWJDK5_MASK;
1747
}
1748
1749
/* ACC_STRICT doesn't exist for older .class files prior to Java 2 */
1750
/* Xfuture qualification added to pass CLDC TCK mthacc00601m5_1 - wants 45.3 class file rejected with ACC_STRICT set */
1751
/* Test exclusion request pending - will revert on success */
1752
if ((classfileVersion < BCT_JavaMajorVersionShifted(2)) && ((flags & CFR_Xfuture) == 0)) {
1753
value &= ~CFR_ACC_STRICT;
1754
}
1755
1756
/* the rules don't apply to <clinit> (see JVMS 4.6) */
1757
if (nameIndexOK && utf8Equal(&classfile->constantPool[method->nameIndex], "<clinit>", 8)) {
1758
/* JVMS 4.6: Methods: access_flags:
1759
* the only flag that we're supposed to honour on <clinit> is ACC_STRICT.
1760
* JVMS 2.9: Specially named initialization Methods
1761
* "initialization method... is static, takes no args..." Footnote states other
1762
* methods named <clinit> are ignored.
1763
*/
1764
/*
1765
* JVMS 2.9 Java SE 8 Edition:
1766
* In a class file whose version number is 51.0 or above, the method must
1767
* additionally have its ACC_STATIC flag (Section 4.6 Methods) set in order to be the class or interface
1768
* initialization method.
1769
*/
1770
if (classfileVersion < BCT_JavaMajorVersionShifted(7)) {
1771
method->accessFlags |= CFR_ACC_STATIC;
1772
} else if (vmVersionShifted >= BCT_JavaMajorVersionShifted(9)) {
1773
if (J9_ARE_NO_BITS_SET(method->accessFlags, CFR_ACC_STATIC)) {
1774
/* missing code attribute detected elsewhere */
1775
errorCode = J9NLS_CFR_ERR_CLINIT_NOT_STATIC__ID;
1776
goto _errorFound;
1777
}
1778
}
1779
1780
method->accessFlags &= CFR_CLINIT_METHOD_ACCESS_MASK;
1781
goto _nameCheck;
1782
1783
}
1784
1785
if (nameIndexOK && utf8Equal(&classfile->constantPool[method->nameIndex], "<init>", 6)) {
1786
1787
/* check no invalid flags set */
1788
if ((J9_IS_CLASSFILE_VALUETYPE(classfile) && (value & ~CFR_INIT_VT_METHOD_ACCESS_MASK))
1789
|| (!J9_IS_CLASSFILE_VALUETYPE(classfile) && (value & ~CFR_INIT_METHOD_ACCESS_MASK))
1790
) {
1791
errorCode = J9NLS_CFR_ERR_INIT_METHOD__ID;
1792
goto _errorFound;
1793
}
1794
1795
/* Java SE 9 Edition:
1796
* A method is an instance initialization method if
1797
* it is defined in a class (not an interface).
1798
*/
1799
if (vmVersionShifted >= BCT_JavaMajorVersionShifted(9)) {
1800
if (classfile->accessFlags & CFR_ACC_INTERFACE) {
1801
errorCode = J9NLS_CFR_ERR_INIT_ILLEGAL_IN_INTERFACE__ID;
1802
goto _errorFound;
1803
}
1804
}
1805
}
1806
1807
/* Check interface-method-only access flag constraints. */
1808
if (classfile->accessFlags & CFR_ACC_INTERFACE) {
1809
if (classfileVersion < BCT_JavaMajorVersionShifted(8)) {
1810
U_32 mask = CFR_INTERFACE_METHOD_ACCESS_MASK;
1811
/* Xfuture maintains checks for all the illegal qualifiers for interface methods */
1812
/* Make the normal mode skip checks for some interface method flags */
1813
if ((flags & CFR_Xfuture) == 0) {
1814
/* Contrary to the spec, ACC_STRICT is allowed by Sun for all classes up to and including Java 1.5 */
1815
/* ACC_SYNCHRONIZED is also allowed by Sun, but only for classes before Java 1.5. */
1816
mask |= (CFR_ACC_STRICT | CFR_ACC_SYNCHRONIZED);
1817
}
1818
/* check that there are no flags set that are not allowed AND the required flags are set */
1819
if ((value & ~mask) || ((value & CFR_INTERFACE_METHOD_ACCESS_REQUIRED) != CFR_INTERFACE_METHOD_ACCESS_REQUIRED)) {
1820
errorCode = J9NLS_CFR_ERR_INTERFACE_METHOD__ID;
1821
goto _errorFound;
1822
}
1823
} else {
1824
/* class file version >= 52 (Java 8) */
1825
const U_32 illegalMask = CFR_ACC_PROTECTED | CFR_ACC_FINAL | CFR_ACC_NATIVE | CFR_ACC_SYNCHRONIZED;
1826
const U_32 publicPrivateMask = CFR_ACC_PUBLIC | CFR_ACC_PRIVATE;
1827
/* Use 'n & (n - 1)' to determine if multiple bits are set which test if this is a power of two */
1828
const U_32 maskedValue = value & publicPrivateMask;
1829
BOOLEAN oneOfPublicOrPrivate = (maskedValue != 0) && (((maskedValue) & ((maskedValue) - 1)) == 0);
1830
1831
if ((0 != (value & illegalMask)) || !oneOfPublicOrPrivate) {
1832
errorCode = J9NLS_CFR_ERR_INTERFACE_METHOD_JAVA_8__ID;
1833
goto _errorFound;
1834
}
1835
if ((CFR_ACC_ABSTRACT == (value & CFR_ACC_ABSTRACT)) && (0 != (value & ~CFR_ABSTRACT_METHOD_ACCESS_MASK))) {
1836
errorCode = J9NLS_CFR_ERR_INTERFACE_METHOD_JAVA_8__ID;
1837
goto _errorFound;
1838
}
1839
}
1840
goto _nameCheck;
1841
}
1842
1843
/* handling method of generic classes (non-interface) */
1844
if (value & CFR_ACC_ABSTRACT) {
1845
/* check abstract methods */
1846
if (value & ~CFR_ABSTRACT_METHOD_ACCESS_MASK) {
1847
errorCode = J9NLS_CFR_ERR_ABSTRACT_METHOD__ID;
1848
goto _errorFound;
1849
}
1850
}
1851
1852
/* Check access flag constraints. */
1853
maskedValue = value & CFR_PUBLIC_PRIVATE_PROTECTED_MASK;
1854
1855
/* Check none or only one of the access flags set - result is 0 if no bits or only 1 bit is set */
1856
if (maskedValue & (maskedValue - 1)) {
1857
errorCode = J9NLS_CFR_ERR_ACCESS_CONFLICT_METHOD__ID;
1858
goto _errorFound;
1859
}
1860
1861
_nameCheck:
1862
1863
offset = 2;
1864
/* Name check. */
1865
value = method->nameIndex;
1866
if (!nameIndexOK) {
1867
if ((!value) || (value >= classfile->constantPoolCount)) {
1868
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1869
goto _errorFound;
1870
}
1871
if (classfile->constantPool[value].tag != CFR_CONSTANT_Utf8) {
1872
errorCode = J9NLS_CFR_ERR_BAD_NAME_INDEX__ID;
1873
goto _errorFound;
1874
}
1875
}
1876
/* method names are checked for well-formedness by the static verifier */
1877
1878
offset = 4;
1879
/* Check signature. */
1880
value = method->descriptorIndex;
1881
if ((!value) || (value >= classfile->constantPoolCount)) {
1882
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1883
goto _errorFound;
1884
}
1885
if (classfile->constantPool[value].tag != CFR_CONSTANT_Utf8) {
1886
errorCode = J9NLS_CFR_ERR_BAD_DESCRIPTOR_INDEX__ID;
1887
goto _errorFound;
1888
}
1889
/* staticverify.c checks the method signature */
1890
/* Check the attributes. */
1891
if (checkAttributes(portLib, classfile, method->attributes, method->attributesCount, segment, -1, OUTSIDE_CODE, flags)) {
1892
return -1;
1893
}
1894
1895
if (method->codeAttribute) {
1896
if (method->codeAttribute->codeLength > 65535) {
1897
errorCode = J9NLS_CFR_ERR_CODE_ARRAY_TOO_LARGE__ID;
1898
goto _errorFound;
1899
}
1900
if (J9_ARE_ANY_BITS_SET(method->accessFlags, CFR_ACC_NATIVE | CFR_ACC_ABSTRACT)) {
1901
errorCode = J9NLS_CFR_ERR_CODE_FOR_ABSTRACT_OR_NATIVE__ID;
1902
goto _errorFound;
1903
}
1904
}
1905
1906
/* 97986 check the validity in ClassFileOracle::walkMethodMethodParametersAttribute */
1907
}
1908
return 0;
1909
1910
_errorFound:
1911
1912
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, method->romAddress + offset);
1913
return -1;
1914
}
1915
1916
1917
/*
1918
Read the attributes from the bytes in @data.
1919
@param maxBootstrapMethodIndex maximum bootstrap method index used by InvokeDynamic. Set to -1 to ignore.
1920
@return 0 on success, non-zero on failure.
1921
*/
1922
static I_32
1923
checkAttributes(J9PortLibrary* portLib, J9CfrClassFile* classfile, J9CfrAttribute** attributes, U_32 attributesCount, U_8* segment, I_32 maxBootstrapMethodIndex, U_32 extra, U_32 flags)
1924
{
1925
J9CfrAttribute* attrib;
1926
J9CfrAttributeCode* code;
1927
J9CfrAttributeExceptions* exceptions;
1928
J9CfrExceptionTableEntry* exception;
1929
J9CfrAttributeInnerClasses* classes = NULL;
1930
J9CfrAttributeEnclosingMethod* enclosing = NULL;
1931
J9CfrConstantPoolInfo* cpBase;
1932
U_32 value, errorCode, errorType, cpCount;
1933
U_32 i, j, k;
1934
UDATA foundStackMap = FALSE;
1935
BOOLEAN bootstrapMethodAttributeRead = FALSE;
1936
BOOLEAN enablePermittedSubclassErrors = FALSE;
1937
I_32* innerClassArrayIndexTable = NULL;
1938
1939
PORT_ACCESS_FROM_PORT(portLib);
1940
1941
errorType = CFR_ThrowClassFormatError;
1942
cpBase = classfile->constantPool;
1943
cpCount = (U_32) classfile->constantPoolCount;
1944
1945
for(i = 0; i < attributesCount; i++) {
1946
attrib = attributes[i];
1947
switch(attrib->tag) {
1948
case CFR_ATTRIBUTE_SourceFile:
1949
value = ((J9CfrAttributeSourceFile*)attrib)->sourceFileIndex;
1950
if((!value)||(value >= cpCount)) {
1951
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1952
goto _errorFound;
1953
}
1954
if(cpBase[value].tag != CFR_CONSTANT_Utf8) {
1955
errorCode = J9NLS_CFR_ERR_SOURCE_FILE_INDEX__ID;
1956
goto _errorFound;
1957
}
1958
break;
1959
1960
case CFR_ATTRIBUTE_Signature:
1961
value = ((J9CfrAttributeSignature*)attrib)->signatureIndex;
1962
if((0 == value)||(value >= cpCount)) {
1963
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1964
goto _errorFound;
1965
}
1966
if(cpBase[value].tag != CFR_CONSTANT_Utf8) {
1967
errorCode = J9NLS_CFR_ERR_BC_INVALID_SIG__ID;
1968
goto _errorFound;
1969
}
1970
break;
1971
1972
case CFR_ATTRIBUTE_ConstantValue:
1973
value = ((J9CfrAttributeConstantValue*)attrib)->constantValueIndex;
1974
if((0 == value)||(value >= cpCount)) {
1975
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
1976
goto _errorFound;
1977
}
1978
switch(cpBase[value].tag) {
1979
case CFR_CONSTANT_Integer:
1980
case CFR_CONSTANT_Float:
1981
case CFR_CONSTANT_Long:
1982
case CFR_CONSTANT_Double:
1983
case CFR_CONSTANT_String:
1984
break;
1985
1986
default:
1987
errorCode = J9NLS_CFR_ERR_CONSTANT_VALUE_INDEX__ID;
1988
goto _errorFound;
1989
}
1990
break;
1991
1992
case CFR_ATTRIBUTE_Code:
1993
code = (J9CfrAttributeCode*)attrib;
1994
if(code->codeLength == 0) {
1995
errorCode = J9NLS_CFR_ERR_CODE_ARRAY_EMPTY__ID;
1996
goto _errorFound;
1997
}
1998
1999
for(j = 0; j < code->exceptionTableLength; j++) {
2000
exception = &(code->exceptionTable[j]);
2001
value = exception->catchType;
2002
if(value >= cpCount) {
2003
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2004
goto _errorFound;
2005
}
2006
if((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Class)) {
2007
errorCode = J9NLS_CFR_ERR_CATCH_NOT_CLASS__ID;
2008
goto _errorFound;
2009
}
2010
}
2011
2012
if(checkAttributes(portLib, classfile, code->attributes, code->attributesCount, segment, -1, code->codeLength, flags)) {
2013
return -1;
2014
}
2015
break;
2016
2017
case CFR_ATTRIBUTE_Exceptions:
2018
exceptions = (J9CfrAttributeExceptions*)attrib;
2019
for(j = 0; j < exceptions->numberOfExceptions; j++) {
2020
value = exceptions->exceptionIndexTable[j];
2021
if((0 == value)||(value >= cpCount)) {
2022
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2023
goto _errorFound;
2024
}
2025
if(cpBase[value].tag != CFR_CONSTANT_Class) {
2026
errorCode = J9NLS_CFR_ERR_EXCEPTION_NOT_CLASS__ID;
2027
goto _errorFound;
2028
}
2029
}
2030
break;
2031
2032
case CFR_ATTRIBUTE_MethodParameters:
2033
{
2034
/* 97986 Errors here are not fatal. Check the validity in ClassFileOracle::walkMethodMethodParametersAttribute */
2035
break;
2036
}
2037
case CFR_ATTRIBUTE_LineNumberTable:
2038
value = ((J9CfrAttributeLineNumberTable*)attrib)->lineNumberTableLength;
2039
for(j = 0; j < value; j++) {
2040
if(((J9CfrAttributeLineNumberTable*)attrib)->lineNumberTable[j].startPC >= extra) {
2041
errorCode = J9NLS_CFR_ERR_LINE_NUMBER_PC__ID;
2042
goto _errorFound;
2043
}
2044
}
2045
break;
2046
2047
case CFR_ATTRIBUTE_LocalVariableTable:
2048
for(j = 0; j < ((J9CfrAttributeLocalVariableTable*)attrib)->localVariableTableLength; j++) {
2049
value = ((J9CfrAttributeLocalVariableTable*)attrib)->localVariableTable[j].startPC;
2050
if(value > extra) {
2051
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_START__ID;
2052
goto _errorFound;
2053
}
2054
2055
if(((J9CfrAttributeLocalVariableTable*)attrib)->localVariableTable[j].length + value > extra) {
2056
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_LENGTH__ID;
2057
goto _errorFound;
2058
}
2059
2060
value = ((J9CfrAttributeLocalVariableTable*)attrib)->localVariableTable[j].nameIndex;
2061
if((0 == value)||(value >= cpCount)) {
2062
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2063
goto _errorFound;
2064
}
2065
if(cpBase) {
2066
if(cpBase[value].tag != CFR_CONSTANT_Utf8) {
2067
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_NAME_NOT_UTF8__ID;
2068
goto _errorFound;
2069
}
2070
if((flags & CFR_Xfuture) && (bcvCheckName(&cpBase[value]))) {
2071
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_NAME__ID;
2072
goto _errorFound;
2073
}
2074
}
2075
2076
value = ((J9CfrAttributeLocalVariableTable*)attrib)->localVariableTable[j].descriptorIndex;
2077
if((0 == value)||(value >= cpCount)) {
2078
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2079
goto _errorFound;
2080
}
2081
if(cpBase) {
2082
if(cpBase[value].tag != CFR_CONSTANT_Utf8) {
2083
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_SIGNATURE_NOT_UTF8__ID;
2084
goto _errorFound;
2085
}
2086
if(j9bcv_checkFieldSignature(&cpBase[value], 0)) {
2087
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_SIGNATURE_INVALID__ID;
2088
goto _errorFound;
2089
}
2090
}
2091
2092
/* index range verification happens in ClassFileOracle.cpp with Xfuture */
2093
}
2094
break;
2095
2096
case CFR_ATTRIBUTE_LocalVariableTypeTable:
2097
for(j = 0; j < ((J9CfrAttributeLocalVariableTypeTable*)attrib)->localVariableTypeTableLength; j++) {
2098
value = ((J9CfrAttributeLocalVariableTypeTable*)attrib)->localVariableTypeTable[j].startPC;
2099
if(value > extra) {
2100
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_START__ID;
2101
goto _errorFound;
2102
}
2103
2104
if(((J9CfrAttributeLocalVariableTypeTable*)attrib)->localVariableTypeTable[j].length + value > extra) {
2105
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_LENGTH__ID;
2106
goto _errorFound;
2107
}
2108
2109
value = ((J9CfrAttributeLocalVariableTypeTable*)attrib)->localVariableTypeTable[j].nameIndex;
2110
if((0 == value)||(value >= cpCount)) {
2111
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2112
goto _errorFound;
2113
}
2114
if(cpBase) {
2115
if(cpBase[value].tag != CFR_CONSTANT_Utf8) {
2116
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_NAME_NOT_UTF8__ID;
2117
goto _errorFound;
2118
}
2119
if((flags & CFR_Xfuture) && (bcvCheckName(&cpBase[value]))) {
2120
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_NAME__ID;
2121
goto _errorFound;
2122
}
2123
}
2124
2125
value = ((J9CfrAttributeLocalVariableTypeTable*)attrib)->localVariableTypeTable[j].signatureIndex;
2126
if((0 == value)||(value >= cpCount)) {
2127
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2128
goto _errorFound;
2129
}
2130
if((cpBase)&&(cpBase[value].tag != CFR_CONSTANT_Utf8)) {
2131
errorCode = J9NLS_CFR_ERR_LOCAL_VARIABLE_SIGNATURE_NOT_UTF8__ID;
2132
goto _errorFound;
2133
}
2134
2135
/* index range verification happens in ClassFileOracle.cpp with Xfuture */
2136
}
2137
break;
2138
2139
case CFR_ATTRIBUTE_InnerClasses:
2140
{
2141
BOOLEAN cycleOfInnerClassFound = FALSE;
2142
2143
if (classes != NULL) {
2144
errorCode = J9NLS_CFR_ERR_MULTIPLE_INNER_CLASS_ATTRIBUTES__ID;
2145
goto _errorFound;
2146
}
2147
2148
innerClassArrayIndexTable = j9mem_allocate_memory(cpCount * sizeof(I_32), J9MEM_CATEGORY_CLASSES);
2149
if (NULL == innerClassArrayIndexTable) {
2150
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-2);
2151
return -2;
2152
}
2153
memset(innerClassArrayIndexTable, -1, cpCount * sizeof(I_32));
2154
2155
classes = (J9CfrAttributeInnerClasses*)attrib;
2156
for (j = 0; j < classes->numberOfClasses; j++) {
2157
value = classes->classes[j].innerClassInfoIndex;
2158
if ((0 == value)||(value >= cpCount)) {
2159
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2160
goto _errorFound;
2161
}
2162
if (cpBase[value].tag != CFR_CONSTANT_Class) {
2163
errorCode = J9NLS_CFR_ERR_INNER_CLASS_NOT_CLASS__ID;
2164
goto _errorFound;
2165
}
2166
/* Check class name integrity? */
2167
2168
innerClassArrayIndexTable[value] = j;
2169
2170
value = classes->classes[j].outerClassInfoIndex;
2171
if ((0 != value) && (value >= cpCount)) {
2172
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2173
goto _errorFound;
2174
}
2175
if ((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Class)) {
2176
errorCode = J9NLS_CFR_ERR_OUTER_CLASS_NOT_CLASS__ID;
2177
goto _errorFound;
2178
}
2179
if (0 != value) {
2180
J9CfrConstantPoolInfo* outerClassInfoUtf8 = &cpBase[cpBase[value].slot1];
2181
if (CFR_CONSTANT_Utf8 != outerClassInfoUtf8->tag) {
2182
errorCode = J9NLS_CFR_ERR_OUTER_CLASS_NAME_NOT_UTF8__ID;
2183
goto _errorFound;
2184
}
2185
if (0 == outerClassInfoUtf8->slot1) {
2186
errorCode = J9NLS_CFR_ERR_OUTER_CLASS_UTF8_ZERO_LENGTH__ID;
2187
goto _errorFound;
2188
}
2189
/* Capture the error if the outer_class_info_index points to an array class */
2190
if ('[' == outerClassInfoUtf8->bytes[0]) {
2191
errorCode = J9NLS_CFR_ERR_OUTER_CLASS_BAD_ARRAY_CLASS__ID;
2192
goto _errorFound;
2193
}
2194
}
2195
/* Check class name integrity? */
2196
2197
value = classes->classes[j].innerNameIndex;
2198
if ((0 != value) && (value >= cpCount)) {
2199
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2200
goto _errorFound;
2201
}
2202
if ((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Utf8)) {
2203
errorCode = J9NLS_CFR_ERR_INNER_NAME_NOT_UTF8__ID;
2204
goto _errorFound;
2205
}
2206
/* Check class name integrity? */
2207
}
2208
2209
/* Detect whether the cycle of the same inner class exists in the InnerClass attribute */
2210
for (j = 0; ((j < classes->numberOfClasses) && !cycleOfInnerClassFound); j++) {
2211
U_32 valueInnerClassInfoIndex = classes->classes[j].innerClassInfoIndex;
2212
U_32 valueOuterClassInfoIndex = classes->classes[j].outerClassInfoIndex;
2213
J9CfrConstantPoolInfo* innerClassInfoUtf8 = &cpBase[cpBase[valueInnerClassInfoIndex].slot1];
2214
J9CfrConstantPoolInfo* outerClassInfoUtf8 = &cpBase[cpBase[valueOuterClassInfoIndex].slot1];
2215
I_32 nextInnerClassArrayIndex = -1;
2216
2217
while (!cycleOfInnerClassFound) {
2218
if (utf8EqualUtf8(innerClassInfoUtf8, outerClassInfoUtf8)) {
2219
cycleOfInnerClassFound = TRUE;
2220
break;
2221
}
2222
2223
nextInnerClassArrayIndex = innerClassArrayIndexTable[valueOuterClassInfoIndex];
2224
if (nextInnerClassArrayIndex >= 0) {
2225
valueOuterClassInfoIndex = classes->classes[nextInnerClassArrayIndex].outerClassInfoIndex;
2226
outerClassInfoUtf8 = &cpBase[cpBase[valueOuterClassInfoIndex].slot1];
2227
} else {
2228
break;
2229
}
2230
}
2231
}
2232
2233
/* Duplicate class check only when the cycle of the same inner class doesn't exist in the InnerClass attribute */
2234
if (!cycleOfInnerClassFound) {
2235
for (j = 0; j < classes->numberOfClasses; j++) {
2236
for (k = j + 1; k < classes->numberOfClasses; k++) {
2237
if (classes->classes[j].innerClassInfoIndex == classes->classes[k].innerClassInfoIndex) {
2238
errorCode = J9NLS_CFR_ERR_DUPLICATE_INNER_CLASS_ENTRY__ID;
2239
goto _errorFound;
2240
}
2241
}
2242
}
2243
}
2244
2245
if (NULL != innerClassArrayIndexTable) {
2246
j9mem_free_memory(innerClassArrayIndexTable);
2247
innerClassArrayIndexTable = NULL;
2248
}
2249
break;
2250
}
2251
case CFR_ATTRIBUTE_EnclosingMethod:
2252
if (enclosing != NULL) {
2253
errorCode = J9NLS_CFR_ERR_MULTIPLE_ENCLOSING_METHOD_ATTRIBUTES__ID;
2254
goto _errorFound;
2255
}
2256
enclosing = (J9CfrAttributeEnclosingMethod*)attrib;
2257
value = enclosing->classIndex;
2258
if ((0 == value) || (value >= cpCount)) {
2259
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2260
goto _errorFound;
2261
}
2262
if(cpBase[value].tag != CFR_CONSTANT_Class) {
2263
errorCode = J9NLS_CFR_ERR_ENCLOSING_METHOD_CLASS_INDEX_NOT_CLASS__ID;
2264
goto _errorFound;
2265
}
2266
2267
value = enclosing->methodIndex;
2268
if(value >= cpCount) {
2269
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2270
goto _errorFound;
2271
}
2272
if((0 != value) && (cpBase[value].tag != CFR_CONSTANT_NameAndType)) {
2273
errorCode = J9NLS_CFR_ERR_ENCLOSING_METHOD_METHOD_INDEX_NOT_NAME_AND_TYPE__ID;
2274
goto _errorFound;
2275
}
2276
break;
2277
2278
case CFR_ATTRIBUTE_BootstrapMethods:
2279
{
2280
J9CfrAttributeBootstrapMethods* bootstrapMethods = (J9CfrAttributeBootstrapMethods *) attrib;
2281
2282
if (maxBootstrapMethodIndex >= (I_32) bootstrapMethods->numberOfBootstrapMethods) {
2283
errorCode = J9NLS_CFR_ERR_BOOTSTRAP_METHOD_TABLE_ABSENT_OR_WRONG_SIZE__ID;
2284
goto _errorFound;
2285
}
2286
bootstrapMethodAttributeRead = TRUE;
2287
for (j = 0; j < bootstrapMethods->numberOfBootstrapMethods; j++) {
2288
U_16 numberOfBootstrapArguments = 0;
2289
J9CfrBootstrapMethod *bsm = &bootstrapMethods->bootstrapMethods[j];
2290
value = bsm->bootstrapMethodIndex;
2291
if ((0 == value) || (value >= cpCount)) {
2292
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2293
goto _errorFound;
2294
}
2295
if (cpBase[value].tag != CFR_CONSTANT_MethodHandle) {
2296
errorCode = J9NLS_CFR_ERR_BOOTSTRAP_METHODHANDLE__ID;
2297
goto _errorFound;
2298
}
2299
2300
numberOfBootstrapArguments = bsm->numberOfBootstrapArguments;
2301
for (k = 0; k < numberOfBootstrapArguments; k++) {
2302
U_8 cpValueTag = 0;
2303
value = bsm->bootstrapArguments[k];
2304
2305
if ((0 == value) || (value >= cpCount)) {
2306
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2307
goto _errorFound;
2308
}
2309
/* Validate the constant_pool indexes stored in the bootstrap_arguments array.
2310
* Note: The constant_pool entry at that index must be a CONSTANT_String_info,
2311
* CONSTANT_Class_info, CONSTANT_Integer_info, CONSTANT_Long_info, CONSTANT_Float_info,
2312
* CONSTANT_Double_info, CONSTANT_MethodHandle_info, CONSTANT_MethodType_info
2313
* or CFR_CONSTANT_Dynamic structure.
2314
*/
2315
cpValueTag = cpBase[value].tag;
2316
switch(cpValueTag) {
2317
case CFR_CONSTANT_String:
2318
case CFR_CONSTANT_Class:
2319
case CFR_CONSTANT_Integer:
2320
case CFR_CONSTANT_Long:
2321
case CFR_CONSTANT_Float:
2322
case CFR_CONSTANT_Double:
2323
case CFR_CONSTANT_MethodHandle:
2324
case CFR_CONSTANT_MethodType:
2325
case CFR_CONSTANT_Dynamic:
2326
break;
2327
default:
2328
errorCode = J9NLS_CFR_ERR_BAD_BOOTSTRAP_ARGUMENT_ENTRY__ID;
2329
buildBootstrapMethodError((J9CfrError *)segment, errorCode, errorType, attrib->romAddress, j, value, cpValueTag);
2330
return -1;
2331
}
2332
}
2333
}
2334
}
2335
break;
2336
2337
case CFR_ATTRIBUTE_StackMapTable:
2338
if (extra == OUTSIDE_CODE) {
2339
errorCode = J9NLS_CFR_ERR_STACK_MAP_ATTRIBUTE_OUTSIDE_CODE_ATTRIBUTE__ID;
2340
goto _errorFound;
2341
}
2342
if (foundStackMap) {
2343
errorCode = J9NLS_CFR_ERR_MULTIPLE_STACK_MAP_ATTRIBUTES__ID;
2344
goto _errorFound;
2345
}
2346
foundStackMap = TRUE;
2347
2348
break;
2349
2350
case CFR_ATTRIBUTE_Record:
2351
value = ((J9CfrAttributeRecord*)attrib)->nameIndex;
2352
if ((0 == value) || (value >= cpCount)) {
2353
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2354
goto _errorFound;
2355
}
2356
if ((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Utf8)) {
2357
errorCode = J9NLS_CFR_ERR_RECORD_NAME_NOT_UTF8__ID;
2358
goto _errorFound;
2359
}
2360
2361
for (j = 0; j < ((J9CfrAttributeRecord*)attrib)->numberOfRecordComponents; j++) {
2362
J9CfrRecordComponent* recordComponent = &(((J9CfrAttributeRecord*)attrib)->recordComponents[j]);
2363
value = recordComponent->nameIndex;
2364
if ((0 == value) || (value >= cpCount)) {
2365
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2366
goto _errorFound;
2367
}
2368
if ((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Utf8)) {
2369
errorCode = J9NLS_CFR_ERR_RECORD_COMPONENT_NAME_NOT_UTF8__ID;
2370
goto _errorFound;
2371
}
2372
value = recordComponent->descriptorIndex;
2373
if ((0 == value) || (value >= cpCount)) {
2374
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2375
goto _errorFound;
2376
}
2377
if ((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Utf8)) {
2378
errorCode = J9NLS_CFR_ERR_RECORD_COMPONENT_DESCRIPTOR_NOT_UTF8__ID;
2379
goto _errorFound;
2380
}
2381
if (checkAttributes(portLib, classfile, recordComponent->attributes, recordComponent->attributesCount, segment, -1, OUTSIDE_CODE, flags)) {
2382
return -1;
2383
}
2384
}
2385
2386
break;
2387
2388
case CFR_ATTRIBUTE_PermittedSubclasses:
2389
/* PermittedSubclasses verification is for Java version >= 15 */
2390
if ((classfile->majorVersion > 59)
2391
|| ((59 == classfile->majorVersion) && (65535 == classfile->minorVersion))
2392
) {
2393
enablePermittedSubclassErrors = TRUE;
2394
}
2395
2396
/* JVMS: If the ACC_FINAL flag is set, then the ClassFile structure must not have a PermittedSubclasses attribute. */
2397
if (J9_ARE_ANY_BITS_SET(classfile->accessFlags, CFR_ACC_FINAL)) {
2398
if (enablePermittedSubclassErrors) {
2399
errorCode = J9NLS_CFR_FINAL_CLASS_CANNOT_BE_SEALED__ID;
2400
goto _errorFound;
2401
}
2402
break;
2403
}
2404
2405
value = ((J9CfrAttributePermittedSubclasses*)attrib)->nameIndex;
2406
if ((0 == value) || (value >= cpCount)) {
2407
if (enablePermittedSubclassErrors) {
2408
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2409
goto _errorFound;
2410
}
2411
break;
2412
}
2413
if ((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Utf8)) {
2414
if (enablePermittedSubclassErrors) {
2415
errorCode = J9NLS_CFR_ERR_PERMITTEDSUBCLASSES_NAME_NOT_UTF8__ID;
2416
goto _errorFound;
2417
}
2418
break;
2419
}
2420
2421
for (j = 0; j < ((J9CfrAttributePermittedSubclasses*)attrib)->numberOfClasses; j++) {
2422
value = ((J9CfrAttributePermittedSubclasses*)attrib)->classes[j];
2423
if ((0 == value) || (value >= cpCount)) {
2424
if (enablePermittedSubclassErrors) {
2425
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2426
goto _errorFound;
2427
}
2428
break;
2429
}
2430
if ((0 != value) && (cpBase[value].tag != CFR_CONSTANT_Class)) {
2431
if (enablePermittedSubclassErrors) {
2432
errorCode = J9NLS_CFR_ERR_PERMITTEDSUBCLASSES_CLASS_ENTRY_NOT_CLASS_TYPE__ID;
2433
goto _errorFound;
2434
}
2435
break;
2436
}
2437
}
2438
break;
2439
2440
#if JAVA_SPEC_VERSION >= 11
2441
case CFR_ATTRIBUTE_NestHost:
2442
value = ((J9CfrAttributeNestHost*)attrib)->hostClassIndex;
2443
if ((!value) || (value >= cpCount)) {
2444
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2445
goto _errorFound;
2446
}
2447
if (CFR_CONSTANT_Class != cpBase[value].tag) {
2448
errorCode = J9NLS_CFR_ERR_BAD_NEST_HOST_INDEX__ID;
2449
goto _errorFound;
2450
}
2451
break;
2452
2453
case CFR_ATTRIBUTE_NestMembers: {
2454
U_16 nestMembersCount = ((J9CfrAttributeNestMembers*)attrib)->numberOfClasses;
2455
for (j = 0; j < nestMembersCount; j++) {
2456
value = ((J9CfrAttributeNestMembers*)attrib)->classes[j];
2457
if ((0 == value) || (value >= cpCount)) {
2458
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2459
goto _errorFound;
2460
}
2461
if (CFR_CONSTANT_Class != cpBase[value].tag) {
2462
errorCode = J9NLS_CFR_ERR_NEST_MEMBERS_NAME_NOT_CONSTANT_CLASS__ID;
2463
goto _errorFound;
2464
}
2465
}
2466
break;
2467
}
2468
#endif /* JAVA_SPEC_VERSION >= 11 */
2469
2470
case CFR_ATTRIBUTE_StackMap: /* CLDC StackMap attribute - not supported in J2SE */
2471
case CFR_ATTRIBUTE_Synthetic:
2472
case CFR_ATTRIBUTE_Deprecated:
2473
case CFR_ATTRIBUTE_StrippedLineNumberTable:
2474
case CFR_ATTRIBUTE_StrippedLocalVariableTable:
2475
case CFR_ATTRIBUTE_StrippedInnerClasses:
2476
case CFR_ATTRIBUTE_StrippedUnknown:
2477
case CFR_ATTRIBUTE_Unknown:
2478
break;
2479
}
2480
}
2481
2482
if (!bootstrapMethodAttributeRead && (maxBootstrapMethodIndex >= 0)) {
2483
errorCode = J9NLS_CFR_ERR_BOOTSTRAP_METHOD_TABLE_ABSENT_OR_WRONG_SIZE__ID;
2484
buildError((J9CfrError *) segment, errorCode, errorType, 0);
2485
return -1;
2486
}
2487
2488
return 0;
2489
2490
_errorFound:
2491
if (NULL != innerClassArrayIndexTable) {
2492
j9mem_free_memory(innerClassArrayIndexTable);
2493
innerClassArrayIndexTable = NULL;
2494
}
2495
2496
buildError((J9CfrError *) segment, errorCode, errorType, attrib->romAddress);
2497
return -1;
2498
}
2499
2500
2501
/*
2502
* Java allows non-zero minor versions if the major version is less than
2503
* the max supported version for this release:
2504
* Java 8 - v52
2505
* Java 11 - v55
2506
* Java 12 - v56
2507
*
2508
* Starting in Java 12, only 0 & -1 are valid minor versions for classfiles with
2509
* version >= 56. The -1 version is only allowed when combined with the max
2510
* supported version for this release and the --enable-preview flag is specified.
2511
*
2512
* Returns -1 on error, 0 on success.
2513
*/
2514
2515
static I_32
2516
checkClassVersion(J9CfrClassFile* classfile, U_8* segment, U_32 vmVersionShifted, U_32 flags)
2517
{
2518
const U_32 offset = 6;
2519
const U_16 max_allowed_version = vmVersionShifted >> BCT_MajorClassFileVersionMaskShift;
2520
const U_16 majorVersion = classfile->majorVersion;
2521
const U_16 minorVersion = classfile->minorVersion;
2522
U_32 errorCode = J9NLS_CFR_ERR_MAJOR_VERSION__ID;
2523
2524
/* Support versions 45.0 -> <whatever is legal for this VM> */
2525
if (majorVersion == max_allowed_version) {
2526
errorCode = J9NLS_CFR_ERR_MINOR_VERSION__ID;
2527
if (0 == minorVersion) {
2528
return 0;
2529
} else if (0xffff == minorVersion) {
2530
errorCode = J9NLS_CFR_ERR_PREVIEW_VERSION__ID;
2531
/* Preview flags won't be set for Java 8 & earlier (excluding cfdump) */
2532
if (J9_ARE_ANY_BITS_SET(flags, BCT_AnyPreviewVersion | BCT_EnablePreview)) {
2533
return 0;
2534
}
2535
}
2536
} else if ((majorVersion >= 45) && (majorVersion < max_allowed_version)) {
2537
errorCode = J9NLS_CFR_ERR_MINOR_VERSION__ID;
2538
if (majorVersion <= 55) {
2539
/* versions prior to and including Java 11, allow any minor */
2540
return 0;
2541
}
2542
/* only .0 is the only valid minor version for this range */
2543
if (0 == minorVersion) {
2544
return 0;
2545
}
2546
if (0xffff == minorVersion) {
2547
errorCode = J9NLS_CFR_ERR_PREVIEW_VERSION__ID;
2548
/* Allow cfdump to dump preview classes from other releases */
2549
if (J9_ARE_ANY_BITS_SET(flags, BCT_AnyPreviewVersion)) {
2550
return 0;
2551
}
2552
}
2553
}
2554
2555
buildError((J9CfrError *) segment, errorCode, CFR_ThrowUnsupportedClassVersionError, offset);
2556
return -1;
2557
}
2558
2559
/*
2560
Check the class file in @classfile.
2561
Returns -1 on error, 0 on success.
2562
*/
2563
2564
static I_32
2565
checkClass(J9PortLibrary *portLib, J9CfrClassFile* classfile, U_8* segment, U_32 endOfConstantPool, U_32 vmVersionShifted, U_32 flags)
2566
{
2567
U_32 value, errorCode, offset;
2568
U_32 i;
2569
I_32 maxBootstrapMethodIndex = -1;
2570
2571
if(checkPool(classfile, segment, (U_8*)10, &maxBootstrapMethodIndex, flags)) {
2572
return -1;
2573
}
2574
2575
value = classfile->accessFlags & CFR_CLASS_ACCESS_MASK;
2576
2577
if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(5)) {
2578
value &= ~CFR_CLASS_ACCESS_NEWJDK5_MASK;
2579
2580
/* Remove ACC_SUPER from interface tests on older classes */
2581
/* ACC_SUPER is often set in older interfaces */
2582
if (value & CFR_ACC_INTERFACE) {
2583
value &= ~CFR_ACC_SUPER;
2584
}
2585
}
2586
2587
/* the check for ACC_INTERFACE & ACC_ABSTRACT done in j9bcutil_readClassFileBytes */
2588
2589
if ((value & CFR_ACC_ANNOTATION) && (! (value & CFR_ACC_INTERFACE))) {
2590
errorCode = J9NLS_CFR_ERR_ANNOTATION_NOT_INTERFACE__ID;
2591
offset = endOfConstantPool;
2592
goto _errorFound;
2593
}
2594
2595
if ((value & CFR_ACC_FINAL)&&(value & CFR_ACC_ABSTRACT)) {
2596
errorCode = J9NLS_CFR_ERR_FINAL_ABSTRACT_CLASS__ID;
2597
offset = endOfConstantPool;
2598
goto _errorFound;
2599
}
2600
2601
/* check annotations and interfaces for invalid flags */
2602
if ((value & CFR_ACC_INTERFACE) && (value & ~CFR_INTERFACE_CLASS_ACCESS_MASK))
2603
{
2604
errorCode = J9NLS_CFR_ERR_INTERFACE_CLASS__ID;
2605
offset = endOfConstantPool;
2606
goto _errorFound;
2607
}
2608
2609
value = classfile->thisClass;
2610
if ((!value)||(value >= classfile->constantPoolCount)) {
2611
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2612
offset = endOfConstantPool + 2;
2613
goto _errorFound;
2614
}
2615
2616
if ((classfile->constantPool) && (classfile->constantPool[value].tag != CFR_CONSTANT_Class)) {
2617
errorCode = J9NLS_CFR_ERR_NOT_CLASS__ID;
2618
offset = endOfConstantPool + 2;
2619
goto _errorFound;
2620
}
2621
if ((classfile->constantPool) && (CFR_CONSTANT_Class == classfile->constantPool[value].tag)) {
2622
value = classfile->constantPool[classfile->thisClass].slot1;
2623
if (J9_ARE_ALL_BITS_SET(classfile->constantPool[value].flags1, CFR_FOUND_SEPARATOR_IN_MUE_FORM) && (classfile->majorVersion < 48)) {
2624
errorCode = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;
2625
offset = endOfConstantPool + 2;
2626
goto _errorFound;
2627
}
2628
}
2629
2630
value = classfile->superClass;
2631
if (value >= classfile->constantPoolCount) {
2632
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2633
offset = endOfConstantPool + 4;
2634
goto _errorFound;
2635
}
2636
2637
if (0 == value) {
2638
/* Check against j.l.O. */
2639
if(!utf8Equal(&classfile->constantPool[classfile->constantPool[classfile->thisClass].slot1], "java/lang/Object", 16)) {
2640
errorCode = J9NLS_CFR_ERR_NULL_SUPER__ID;
2641
offset = endOfConstantPool + 4;
2642
goto _errorFound;
2643
}
2644
} else if (classfile->constantPool[value].tag != CFR_CONSTANT_Class) {
2645
errorCode = J9NLS_CFR_ERR_SUPER_NOT_CLASS__ID;
2646
offset = endOfConstantPool + 4;
2647
goto _errorFound;
2648
}
2649
2650
for (i = 0; i < classfile->interfacesCount; i++) {
2651
U_32 j;
2652
J9CfrConstantPoolInfo* cpInfo;
2653
value = classfile->interfaces[i];
2654
if((!value)||(value >= classfile->constantPoolCount)) {
2655
errorCode = J9NLS_CFR_ERR_BAD_INDEX__ID;
2656
offset = endOfConstantPool + 4 + (i << 1);
2657
goto _errorFound;
2658
}
2659
cpInfo = &classfile->constantPool[value];
2660
if(cpInfo->tag != CFR_CONSTANT_Class) {
2661
errorCode = J9NLS_CFR_ERR_INTERFACE_NOT_CLASS__ID;
2662
offset = endOfConstantPool + 4 + (i << 1);
2663
goto _errorFound;
2664
}
2665
/* check that this interface isn't a duplicate */
2666
for (j = 0; j < i; j++) {
2667
U_32 otherValue = classfile->interfaces[j];
2668
J9CfrConstantPoolInfo* otherCpInfo = &classfile->constantPool[otherValue];
2669
if(utf8EqualUtf8(&classfile->constantPool[cpInfo->slot1], &classfile->constantPool[otherCpInfo->slot1])) {
2670
errorCode = J9NLS_CFR_ERR_DUPLICATE_INTERFACE__ID;
2671
offset = endOfConstantPool + 4 + (i << 1);
2672
goto _errorFound;
2673
}
2674
}
2675
}
2676
2677
/* Check that interfaces subclass object. */
2678
if (classfile->accessFlags & CFR_ACC_INTERFACE) {
2679
/* Check against j.l.O. */
2680
if(!utf8Equal(&classfile->constantPool[classfile->constantPool[classfile->superClass].slot1], "java/lang/Object", 16)) {
2681
errorCode = J9NLS_CFR_ERR_INTERFACE_SUPER_NOT_OBJECT__ID;
2682
offset = endOfConstantPool + 4 + (i << 1);
2683
goto _errorFound;
2684
}
2685
}
2686
2687
if (checkFields(portLib, classfile, segment, flags)) {
2688
return -1;
2689
}
2690
2691
if (checkMethods(portLib, classfile, segment, vmVersionShifted, flags)) {
2692
return -1;
2693
}
2694
2695
if (checkDuplicateMembers(portLib, classfile, segment, flags, (UDATA) sizeof(J9CfrField))) {
2696
return -1;
2697
}
2698
2699
if (checkDuplicateMembers(portLib, classfile, segment, flags, (UDATA) sizeof(J9CfrMethod))) {
2700
return -1;
2701
}
2702
2703
if (checkAttributes(portLib, classfile, classfile->attributes, classfile->attributesCount, segment, maxBootstrapMethodIndex, OUTSIDE_CODE, flags)) {
2704
return -1;
2705
}
2706
2707
return 0;
2708
2709
_errorFound:
2710
2711
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, offset);
2712
return -1;
2713
}
2714
2715
2716
/*
2717
Read the class file from the bytes in @data.
2718
Returns:
2719
-2 on insufficient space
2720
-1 on error
2721
0 on success
2722
(required segment size)
2723
2724
On success, the class file structure is written into the memory segment
2725
provided.
2726
2727
On failure an error structure is written.
2728
2729
If the segment was too small, the data will represent a partial class file and
2730
should not be used.
2731
2732
If the segment was too small for a single class file struct (26 + 4 * sizeof(void*))
2733
a different error is returned.
2734
2735
Supported flags:
2736
CFR_StripDebugAttributes - do not store data for debug attributes
2737
CFR_StaticVerification - verify static constraints for each code array
2738
BCT_BigEndianOutput - ignored
2739
BCT_LittleEndianOutput - ignored
2740
*/
2741
2742
#define VERBOSE_START(phase) \
2743
do { \
2744
if (NULL != verboseContext) { \
2745
romVerboseRecordPhaseStart(verboseContext, phase); \
2746
} \
2747
} while (0)
2748
2749
#define VERBOSE_END(phase) \
2750
do { \
2751
if (NULL != verboseContext) { \
2752
romVerboseRecordPhaseEnd(verboseContext, phase); \
2753
} \
2754
} while (0)
2755
2756
I_32
2757
j9bcutil_readClassFileBytes(J9PortLibrary *portLib,
2758
IDATA (*verifyFunction) (J9PortLibrary *aPortLib, J9CfrClassFile* classfile, U_8* segment, U_8* segmentLength, U_8* freePointer, U_32 vmVersionShifted, U_32 flags, I_32 *hasRET),
2759
U_8* data, UDATA dataLength, U_8* segment, UDATA segmentLength, U_32 flags, U_8** segmentFreePointer, void *verboseContext, UDATA findClassFlags, UDATA romClassSortingThreshold)
2760
{
2761
U_8* dataEnd;
2762
U_8* segmentEnd;
2763
U_8* index;
2764
U_8* freePointer;
2765
U_8* endOfConstantPool;
2766
J9CfrClassFile* classfile;
2767
I_32 result;
2768
UDATA errorCode;
2769
UDATA offset = 0;
2770
UDATA i;
2771
I_32 hasRET = 0;
2772
UDATA syntheticFound = FALSE;
2773
U_32 vmVersionShifted = flags & BCT_MajorClassFileVersionMask;
2774
U_16 constantPoolAllocationSize = 0;
2775
U_16 errorAction = CFR_ThrowClassFormatError;
2776
2777
Trc_BCU_j9bcutil_readClassFileBytes_Entry();
2778
2779
/* There must be at least enough space for the classfile struct. */
2780
if (segmentLength < (UDATA) sizeof(J9CfrClassFile)) {
2781
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-2);
2782
return -2;
2783
}
2784
2785
index = data;
2786
dataEnd = data + dataLength;
2787
freePointer = segment;
2788
segmentEnd = segment + segmentLength;
2789
2790
ALLOC(classfile, J9CfrClassFile);
2791
2792
/* Verify the class version before any other checks. */
2793
CHECK_EOF(8); /* magic, minor version, major version */
2794
NEXT_U32(classfile->magic, index);
2795
if (classfile->magic != (U_32) CFR_MAGIC) {
2796
errorCode = J9NLS_CFR_ERR_MAGIC__ID;
2797
offset = index - data - 4;
2798
goto _errorFound;
2799
}
2800
2801
NEXT_U16(classfile->minorVersion, index);
2802
NEXT_U16(classfile->majorVersion, index);
2803
2804
/* Ensure that this is a supported class file version. */
2805
if (checkClassVersion(classfile, segment, vmVersionShifted, flags)) {
2806
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-1);
2807
return -1;
2808
}
2809
2810
if (J9_ARE_ANY_BITS_SET(flags, BCT_BasicCheckOnly)) {
2811
Trc_BCU_j9bcutil_readClassFileBytes_Basic_Check_Exit(0);
2812
return 0;
2813
}
2814
2815
if (J9_ARE_ANY_BITS_SET(findClassFlags, J9_FINDCLASS_FLAG_UNSAFE)) {
2816
flags |= BCT_Unsafe;
2817
}
2818
2819
/* Make sure the structure and static verification below uses the class file version
2820
* number. VM version is maintained in vmVersionShifted.
2821
*/
2822
flags &= ~BCT_MajorClassFileVersionMask;
2823
flags |= ((UDATA) classfile->majorVersion) << BCT_MajorClassFileVersionMaskShift;
2824
2825
CHECK_EOF(2); /* constantPoolCount */
2826
NEXT_U16(classfile->constantPoolCount, index);
2827
2828
constantPoolAllocationSize = classfile->constantPoolCount;
2829
2830
if (constantPoolAllocationSize < 1) {
2831
errorCode = J9NLS_CFR_ERR_CONSTANT_POOL_EMPTY__ID;
2832
offset = index - data - 2;
2833
goto _errorFound;
2834
}
2835
2836
VERBOSE_START(ParseClassFileConstantPool);
2837
/* Space for the constant pool */
2838
2839
if (J9_ARE_ANY_BITS_SET(findClassFlags, J9_FINDCLASS_FLAG_ANON | J9_FINDCLASS_FLAG_HIDDEN)) {
2840
/* Preemptively add new entry to the end of the constantPool for the modified anonClassName.
2841
* If it turns out we dont need it, simply reduce the constantPoolCount by 1, which is
2842
* cheaper than allocating twice.
2843
*
2844
* Can't modify the classfile->constantPoolCount until after readPool is called so
2845
* the classfile is properly parsed. Instead use a temp variable to track the real
2846
* size for allocation, and re-assign to classfile->constantPoolCount later.
2847
*
2848
* If the size of the constantPool is MAX_CONSTANT_POOL_SIZE then throw an OOM.
2849
*/
2850
if (constantPoolAllocationSize == MAX_CONSTANT_POOL_SIZE) {
2851
Trc_BCU_j9bcutil_readClassFileBytes_MaxCPCount();
2852
return BCT_ERR_OUT_OF_MEMORY;
2853
}
2854
constantPoolAllocationSize += 1;
2855
}
2856
2857
if (!ALLOC_ARRAY(classfile->constantPool, constantPoolAllocationSize, J9CfrConstantPoolInfo)) {
2858
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-2);
2859
return -2;
2860
}
2861
2862
/* Read the pool. */
2863
if ((result = readPool(classfile, data, dataEnd, segment, segmentEnd, &index, &freePointer)) != 0) {
2864
Trc_BCU_j9bcutil_readClassFileBytes_Exit(result);
2865
return result;
2866
}
2867
endOfConstantPool = index;
2868
VERBOSE_END(ParseClassFileConstantPool);
2869
2870
CHECK_EOF(8);
2871
classfile->accessFlags = NEXT_U16(classfile->accessFlags, index);
2872
2873
/* class files with the ACC_MODULE flag set cannot be loaded */
2874
if (((flags & BCT_MajorClassFileVersionMask) >= BCT_JavaMajorVersionShifted(9))
2875
&& J9_ARE_ALL_BITS_SET(classfile->accessFlags, CFR_ACC_MODULE)
2876
) {
2877
errorCode = J9NLS_CFR_ERR_MODULE_IS_INVALID_CLASS__ID;
2878
errorAction = CFR_ThrowNoClassDefFoundError;
2879
offset = index - data - 2;
2880
goto _errorFound;
2881
}
2882
2883
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2884
/* Currently value type is built on JDK19, so compare with JDK19 for now. Eventually it may need to compare to JDK20. */
2885
if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(19)) {
2886
classfile->accessFlags &= ~(CFR_ACC_VALUE_TYPE | CFR_ACC_PRIMITIVE_VALUE_TYPE | CFR_ACC_ATOMIC);
2887
}
2888
/*
2889
* TODO This behaviour is based on the LW2 spec http://cr.openjdk.java.net/~fparain/L-world/LW2-JVMS-draft-20181009.pdf.
2890
* In the future the CFR_ACC_VALUE_TYPE class access bit will be replaced by a ValObject subtyping relationship. We will
2891
* likely keep the bit in the romClass class, but it will no longer appear in .class files.
2892
*/
2893
2894
if (J9_ARE_ALL_BITS_SET(classfile->accessFlags, CFR_ACC_PRIMITIVE_VALUE_TYPE)
2895
&& J9_ARE_NO_BITS_SET(classfile->accessFlags, CFR_ACC_VALUE_TYPE)
2896
) {
2897
errorCode = J9NLS_CFR_ERR_VALUE_FLAG_MISSING_ON_PRIMITIVE_CLASS__ID;
2898
offset = index - data - 2;
2899
goto _errorFound;
2900
}
2901
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
2902
2903
/* mask access flags to remove unused access bits */
2904
classfile->accessFlags &= CFR_CLASS_ACCESS_MASK;
2905
classfile->j9Flags = 0;
2906
2907
if ((classfile->accessFlags & (CFR_ACC_INTERFACE | CFR_ACC_ABSTRACT)) == CFR_ACC_INTERFACE) {
2908
if ((flags & BCT_MajorClassFileVersionMask) >= BCT_JavaMajorVersionShifted(6)) {
2909
/* error out for Java 6 and newer versions */
2910
errorCode = J9NLS_CFR_ERR_INTERFACE_NOT_ABSTRACT__ID;
2911
offset = index - data - 2;
2912
goto _errorFound;
2913
} else {
2914
/* Just fix old classfiles */
2915
classfile->accessFlags |= CFR_ACC_ABSTRACT;
2916
}
2917
}
2918
2919
NEXT_U16(classfile->thisClass, index);
2920
NEXT_U16(classfile->superClass, index);
2921
NEXT_U16(classfile->interfacesCount, index);
2922
2923
/* Space for the interfaces */
2924
if(!ALLOC_ARRAY(classfile->interfaces, classfile->interfacesCount, U_16)) {
2925
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-2);
2926
return -2;
2927
}
2928
2929
/* Read the interfaces. */
2930
CHECK_EOF(classfile->interfacesCount << 1);
2931
for(i = 0; i < classfile->interfacesCount; i++) {
2932
NEXT_U16(classfile->interfaces[i], index);
2933
}
2934
2935
CHECK_EOF(2);
2936
NEXT_U16(classfile->fieldsCount, index);
2937
2938
VERBOSE_START(ParseClassFileFields);
2939
/* Space for the fields. */
2940
if(!ALLOC_ARRAY(classfile->fields, classfile->fieldsCount, J9CfrField)) {
2941
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-2);
2942
return -2;
2943
}
2944
2945
/* Read the fields. */
2946
if((result = readFields(classfile, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags)) != 0) {
2947
Trc_BCU_j9bcutil_readClassFileBytes_Exit(result);
2948
return result;
2949
}
2950
VERBOSE_END(ParseClassFileFields);
2951
2952
CHECK_EOF(2);
2953
NEXT_U16(classfile->methodsCount, index);
2954
2955
VERBOSE_START(ParseClassFileMethods);
2956
/* Space for the methods. */
2957
if(!ALLOC_ARRAY(classfile->methods, classfile->methodsCount, J9CfrMethod)) {
2958
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-2);
2959
return -2;
2960
}
2961
2962
/* Read the methods. */
2963
if((result = readMethods(classfile, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags)) != 0) {
2964
Trc_BCU_j9bcutil_readClassFileBytes_Exit(result);
2965
return result;
2966
}
2967
VERBOSE_END(ParseClassFileMethods);
2968
2969
/* sort methods */
2970
if (classfile->methodsCount >= romClassSortingThreshold) {
2971
sortMethodIndex(classfile->constantPool, classfile->methods, 0, classfile->methodsCount - 1);
2972
}
2973
2974
CHECK_EOF(2);
2975
NEXT_U16(classfile->attributesCount, index);
2976
2977
VERBOSE_START(ParseClassFileAttributes);
2978
/* Space for the attributes. */
2979
if(!ALLOC_ARRAY(classfile->attributes, classfile->attributesCount, J9CfrAttribute*)) {
2980
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-2);
2981
return -2;
2982
}
2983
2984
/* Read the attributes. */
2985
if((result = readAttributes(classfile, &(classfile->attributes), classfile->attributesCount, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags, &syntheticFound)) != 0) {
2986
Trc_BCU_j9bcutil_readClassFileBytes_Exit(result);
2987
return result;
2988
}
2989
if (syntheticFound) {
2990
classfile->accessFlags |= CFR_ACC_SYNTHETIC;
2991
}
2992
2993
VERBOSE_END(ParseClassFileAttributes);
2994
2995
VERBOSE_START(ParseClassFileCheckClass);
2996
/* Check the pointer vs. end of file. */
2997
if(index != dataEnd) {
2998
offset = index - data;
2999
if (dataLength < offset) {
3000
errorCode = J9NLS_CFR_ERR_UNEXPECTED_EOF__ID;
3001
offset = dataLength;
3002
} else {
3003
/* Already know file is not too short */
3004
errorCode = J9NLS_CFR_ERR_EXPECTED_EOF__ID;
3005
}
3006
goto _errorFound;
3007
}
3008
3009
classfile->classFileSize = (U_32) dataLength;
3010
3011
/* Structure verification. This is "Pass 1". */
3012
if (0 != (flags & CFR_StaticVerification)) {
3013
if(checkClass(portLib, classfile, segment, (U_32) (endOfConstantPool - data), vmVersionShifted, flags)) {
3014
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-1);
3015
return -1;
3016
}
3017
}
3018
VERBOSE_END(ParseClassFileCheckClass);
3019
3020
VERBOSE_START(ParseClassFileVerifyClass);
3021
/* Static verification. This is the first half of "Pass 2". */
3022
if (0 != (flags & CFR_StaticVerification)) {
3023
if((result = (I_32)(verifyFunction)(portLib, classfile, segment, segmentEnd, freePointer, vmVersionShifted, flags, &hasRET)) != 0) {
3024
Trc_BCU_j9bcutil_readClassFileBytes_Exit(result);
3025
return result;
3026
}
3027
} else {
3028
/* Special checking to look for jsr's if -noverify - the verifyFunction normally scans and tags
3029
* for inlining methods and classes that contain jsr's unless the class file version is 51 or
3030
* greater as jsr / ret are always illegal in that case
3031
*/
3032
if (classfile->majorVersion < 51) {
3033
hasRET = checkForJsrs(classfile);
3034
}
3035
}
3036
VERBOSE_END(ParseClassFileVerifyClass);
3037
3038
/* Set constantPoolCount here to take into account the extra cpEntry for the anonClass name.
3039
* This needs to occur after static verification as the new (last) cpEntry intended for
3040
* the anonClassName is not initialized until ROMClassBuilder::handleAnonClassName() is
3041
* invoked later in building the corresponding ROMClass.
3042
*/
3043
classfile->constantPoolCount = constantPoolAllocationSize;
3044
3045
VERBOSE_START(ParseClassFileInlineJSRs);
3046
/* perform jsr inlining in necessary */
3047
if (((classfile->j9Flags & CFR_J9FLAG_HAS_JSR) == CFR_J9FLAG_HAS_JSR) && ((flags & CFR_LeaveJSRs) == 0)) {
3048
J9JSRIData inlineBuffers;
3049
J9CfrMethod *method;
3050
3051
/*
3052
* JSR 202: Section 4.10.1 - class file version # is 51.0 or greater,
3053
* or the version is 50 and nofallback is specified, neither jsr or jsr_w can be in code array
3054
*/
3055
if ((classfile->majorVersion >= 51)
3056
|| (((flags & J9_VERIFY_NO_FALLBACK) == J9_VERIFY_NO_FALLBACK) && (classfile->majorVersion == 50))
3057
) {
3058
errorCode = J9NLS_CFR_ERR_FOUND_JSR_IN_CLASS_VER_51__ID;
3059
/* Jazz 82615: Ignore the specific method as it can't be determined under such circumstance */
3060
buildMethodErrorWithExceptionDetails((J9CfrError *) segment, errorCode, 0, CFR_ThrowVerifyError, 0, 0, &(classfile->methods[0]), classfile->constantPool, 0, -1, 0);
3061
Trc_BCU_j9bcutil_readClassFileBytes_VerifyError_Exception(((J9CfrError *) segment)->errorCode, getJ9CfrErrorDescription(portLib, (J9CfrError *) segment));
3062
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-1);
3063
return -1;
3064
}
3065
3066
memset (&inlineBuffers, 0, sizeof(J9JSRIData));
3067
inlineBuffers.portLib = portLib;
3068
J9_CFR_ALIGN(freePointer, UDATA);
3069
inlineBuffers.freePointer = freePointer;
3070
inlineBuffers.segmentEnd = segmentEnd;
3071
3072
for (i = 0; i < classfile->methodsCount; i++) {
3073
method = &(classfile->methods[i]);
3074
if ((method->j9Flags & CFR_J9FLAG_HAS_JSR) == CFR_J9FLAG_HAS_JSR) {
3075
inlineBuffers.codeAttribute = method->codeAttribute;
3076
inlineBuffers.sourceBuffer = method->codeAttribute->code;
3077
inlineBuffers.sourceBufferSize = method->codeAttribute->codeLength;
3078
inlineBuffers.constantPool = classfile->constantPool;
3079
inlineBuffers.maxStack = method->codeAttribute->maxStack;
3080
inlineBuffers.maxLocals = method->codeAttribute->maxLocals;
3081
inlineBuffers.flags = flags;
3082
inlineBuffers.bytesAddedByJSRInliner = 0;
3083
3084
Trc_BCU_inlineJsrs_Entry((classfile->constantPool[classfile->constantPool[classfile->thisClass].slot1]).slot1, (classfile->constantPool[classfile->constantPool[classfile->thisClass].slot1]).bytes,
3085
(classfile->constantPool[method->nameIndex]).slot1, (classfile->constantPool[method->nameIndex]).bytes,
3086
(classfile->constantPool[method->descriptorIndex]).slot1, (classfile->constantPool[method->descriptorIndex]).bytes);
3087
inlineJsrs(hasRET, classfile, &inlineBuffers);
3088
3089
if (inlineBuffers.errorCode) {
3090
result = (I_32) inlineBuffers.errorCode;
3091
if (inlineBuffers.errorCode == BCT_ERR_VERIFY_ERROR_INLINING) {
3092
/* Jazz 82615: Set the verbose error type and the local variable index if used for the error message framework */
3093
buildMethodErrorWithExceptionDetails((J9CfrError *)segment, inlineBuffers.verifyError, inlineBuffers.verboseErrorType, CFR_ThrowVerifyError,
3094
(I_32) i, (U_16) inlineBuffers.verifyErrorPC, method, classfile->constantPool, inlineBuffers.errorLocalIndex, -1, 0);
3095
3096
/* Over-ride the default message catalog - inlineJsrs() errors are in the BCV catalog */
3097
((J9CfrError *)segment)->errorCatalog = (U_32) J9NLS_BCV_ERR_NO_ERROR__MODULE;
3098
3099
Trc_BCU_j9bcutil_readClassFileBytes_VerifyError_Exception(((J9CfrError *) segment)->errorCode, getJ9CfrErrorDescription(portLib, (J9CfrError *) segment));
3100
Trc_BCU_inlineJsrs_Exit();
3101
3102
result = -1;
3103
}
3104
releaseInlineBuffers (&inlineBuffers);
3105
Trc_BCU_j9bcutil_readClassFileBytes_Exit(result);
3106
return result;
3107
}
3108
3109
/* Update class file size with amount of bytes added by JSR inliner */
3110
classfile->classFileSize += inlineBuffers.bytesAddedByJSRInliner;
3111
3112
Trc_BCU_inlineJsrs_Exit();
3113
}
3114
}
3115
3116
freePointer = inlineBuffers.freePointer;
3117
releaseInlineBuffers (&inlineBuffers);
3118
3119
/* Backup method bytecodes so that in-place fixup will not ruin the JSR'd versions. */
3120
for (i = 0; i < classfile->methodsCount; i++) {
3121
method = &(classfile->methods[i]);
3122
3123
if (CFR_J9FLAG_HAS_JSR == (method->j9Flags & CFR_J9FLAG_HAS_JSR)) {
3124
/* clear the flag - not needed anymore */
3125
method->j9Flags &= ~CFR_J9FLAG_HAS_JSR;
3126
3127
if (!ALLOC_ARRAY(method->codeAttribute->code, method->codeAttribute->codeLength, U_8)) {
3128
Trc_BCU_inlineJsrs_Exit();
3129
return -2;
3130
}
3131
memcpy(method->codeAttribute->code, method->codeAttribute->originalCode, method->codeAttribute->codeLength);
3132
}
3133
}
3134
3135
/* clear the flag - not needed anymore */
3136
classfile->j9Flags &= ~CFR_J9FLAG_HAS_JSR;
3137
}
3138
VERBOSE_END(ParseClassFileInlineJSRs);
3139
3140
Trc_BCU_j9bcutil_readClassFileBytes_Exit(0);
3141
if (segmentFreePointer != NULL) {
3142
*segmentFreePointer = freePointer;
3143
}
3144
return 0;
3145
3146
_errorFound:
3147
3148
buildError((J9CfrError *) segment, errorCode, errorAction, offset);
3149
3150
switch(errorAction) {
3151
case CFR_ThrowNoClassDefFoundError:
3152
Trc_BCU_j9bcutil_readClassFileBytes_NoClassDefFoundError_Exception(((J9CfrError *) segment)->errorCode, getJ9CfrErrorDescription(portLib, (J9CfrError *) segment));
3153
break;
3154
default:
3155
Trc_BCU_j9bcutil_readClassFileBytes_ClassFormatError_Exception(((J9CfrError *) segment)->errorCode, getJ9CfrErrorDescription(portLib, (J9CfrError *) segment));
3156
}
3157
3158
Trc_BCU_j9bcutil_readClassFileBytes_Exit(-1);
3159
return -1;
3160
}
3161
3162
#undef VERBOSE_START
3163
#undef VERBOSE_END
3164
3165
/*
3166
Compare a J9CfrConstantUtf8 to another J9CfrConstantUtf8.
3167
*/
3168
3169
static BOOLEAN
3170
utf8EqualUtf8(J9CfrConstantPoolInfo *utf8a, J9CfrConstantPoolInfo *utf8b)
3171
{
3172
if (utf8a->tag !=CFR_CONSTANT_Utf8) {
3173
return FALSE;
3174
}
3175
3176
if (utf8a == utf8b) {
3177
return TRUE;
3178
}
3179
3180
/* slot1 contains the length */
3181
if ((utf8b->tag !=CFR_CONSTANT_Utf8) || (utf8a->slot1 != utf8b->slot1)) {
3182
return FALSE;
3183
}
3184
3185
return memcmp (utf8a->bytes, utf8b->bytes, utf8a->slot1) == 0;
3186
}
3187
3188
3189
/*
3190
Verify (pass 1) that fields/members aren't duplicated in @classfile.
3191
Returns 0 on success, non-zero on failure.
3192
3193
This function implements two different algorithms. For a small number
3194
of members (<30) each member is compared to every other member.
3195
For a larger number of members, a hash table is allocated and each
3196
member is placed in the hashtable. When collisions occur, the colliding
3197
elements are checked to see if they are duplicates.
3198
3199
On tiny configurations, only the O(n^2) algorithm is used, as these VMs
3200
are unlikely to encounter very large classes.
3201
*/
3202
3203
static I_32
3204
checkDuplicateMembers (J9PortLibrary* portLib, J9CfrClassFile * classfile, U_8 * segment, U_32 flags, UDATA memberSize)
3205
{
3206
if (flags & CFR_StaticVerification) {
3207
#if DUP_TIMING
3208
PORT_ACCESS_FROM_PORT(portLib);
3209
U_64 startTime;
3210
#endif
3211
J9CfrMember *member;
3212
U_32 i, j, errorCode;
3213
UDATA count;
3214
U_8* data;
3215
3216
if (memberSize == (UDATA) sizeof(J9CfrField)) {
3217
count =classfile->fieldsCount;
3218
data = (U_8*)classfile->fields;
3219
errorCode = J9NLS_CFR_ERR_DUPLICATE_FIELD__ID;
3220
} else {
3221
count = classfile->methodsCount;
3222
data = (U_8*)classfile->methods;
3223
errorCode = J9NLS_CFR_ERR_DUPLICATE_METHOD__ID;
3224
}
3225
3226
if (count >= DUP_HASH_THRESHOLD || DUP_TIMING) {
3227
PORT_ACCESS_FROM_PORT(portLib);
3228
U_16 *sortedIndices;
3229
UDATA tableSize = findSmallestPrimeGreaterThanOrEqualTo(count * 2);
3230
3231
#if DUP_TIMING
3232
startTime = j9time_hires_clock();
3233
#endif
3234
sortedIndices = j9mem_allocate_memory(tableSize * sizeof(U_16), J9MEM_CATEGORY_CLASSES);
3235
/* if the allocate failed, fall through to the in-place search */
3236
if (sortedIndices != NULL) {
3237
I_32 k;
3238
3239
memset(sortedIndices, 0, tableSize * sizeof(U_16));
3240
3241
/* count down, so that 0 is the last index added to the table. This allows
3242
* us to use 0 as the free tag
3243
*/
3244
for (k = (I_32) (count - 1); k >= 0; k--) {
3245
U_32 hash = 0;
3246
J9CfrConstantPoolInfo *name, *sig;
3247
member = (J9CfrMember*)&data[memberSize * k];
3248
name = &classfile->constantPool[member->nameIndex];
3249
sig = &classfile->constantPool[member->descriptorIndex];
3250
3251
/* a 24-bit hash is good enough, since the maximum number of members is 65535 */
3252
for (j = 0; j < name->slot1; j++) {
3253
hash ^= (U_32)RandomValues[name->bytes[j]] << 8;
3254
if (++j < name->slot1) hash ^= (U_32)RandomValues[name->bytes[j]] << 8;
3255
if (++j < name->slot1) hash ^= (U_32)RandomValues[name->bytes[j]] << 16;
3256
}
3257
for (j = 0; j < sig->slot1; j++) {
3258
hash ^= (U_32)RandomValues[sig->bytes[j]] << 8;
3259
if (++j < sig->slot1) hash ^= (U_32)RandomValues[sig->bytes[j]] << 8;
3260
if (++j < sig->slot1) hash ^= (U_32)RandomValues[sig->bytes[j]] << 16;
3261
}
3262
hash %= tableSize;
3263
for (j = hash; sortedIndices[j];) {
3264
J9CfrMember* dup = (J9CfrMember*)&data[memberSize * sortedIndices[j]];
3265
if (memberEqual(classfile, member, dup)) {
3266
goto fail;
3267
}
3268
j = j + 1;
3269
if (j == tableSize) {
3270
j = 0;
3271
}
3272
}
3273
sortedIndices[j] = (U_16) k;
3274
}
3275
3276
j9mem_free_memory(sortedIndices);
3277
#if DUP_TIMING
3278
j9tty_printf(PORTLIB, "Hash table for %6d elements: %lluus\n", count, j9time_hires_delta(startTime, j9time_hires_clock(), J9PORT_TIME_DELTA_IN_MICROSECONDS));
3279
#else
3280
return 0;
3281
#endif
3282
}
3283
}
3284
3285
/* do an in-place, O(n^2) search */
3286
#if DUP_TIMING
3287
startTime = j9time_hires_clock();
3288
#endif
3289
for (i = 0; i < count; i++) {
3290
member = (J9CfrMember*)&data[memberSize * i];
3291
for (j = 0; j < i; j++) {
3292
J9CfrMember *dup = (J9CfrMember*)&data[memberSize * j];
3293
if (memberEqual(classfile, member, dup)) {
3294
fail:
3295
buildError((J9CfrError *) segment, errorCode, CFR_ThrowClassFormatError, member->romAddress);
3296
return -1;
3297
}
3298
}
3299
}
3300
#if DUP_TIMING
3301
j9tty_printf(PORTLIB, "In-place for %8d elements: %lluus\n", count, j9time_hires_delta(startTime, j9time_hires_clock(), J9PORT_TIME_DELTA_IN_MICROSECONDS));
3302
#endif
3303
}
3304
3305
return 0;
3306
}
3307
3308
3309
3310
static BOOLEAN
3311
memberEqual(J9CfrClassFile * classfile, J9CfrMember* a, J9CfrMember* b)
3312
{
3313
return
3314
utf8EqualUtf8 (&classfile->constantPool[a->nameIndex], &classfile->constantPool[b->nameIndex])
3315
&& utf8EqualUtf8 (&classfile->constantPool[a->descriptorIndex], &classfile->constantPool[b->descriptorIndex]);
3316
}
3317
3318
/*
3319
Read the attributes from the bytes in @data.
3320
Returns 0 on success, non-zero on failure.
3321
*/
3322
3323
static I_32
3324
readAnnotations(J9CfrClassFile * classfile, J9CfrAnnotation * pAnnotations, U_32 annotationCount, U_8 * data,
3325
U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags)
3326
{
3327
J9CfrAnnotation *annotationList = pAnnotations;
3328
U_8 *index = *pIndex;
3329
U_8 *freePointer = *pFreePointer;
3330
U_32 errorCode, offset;
3331
U_32 i, j;
3332
I_32 result;
3333
3334
for (i = 0; i < annotationCount; i++) {
3335
CHECK_EOF(4);
3336
NEXT_U16(annotationList[i].typeIndex, index);
3337
if (annotationList[i].typeIndex >= classfile->constantPoolCount ) {
3338
annotationList[i].typeIndex = 0; /* put in safe dummy values in case of error */
3339
annotationList[i].numberOfElementValuePairs = 0;
3340
return BCT_ERR_INVALID_ANNOTATION;
3341
}
3342
NEXT_U16(annotationList[i].numberOfElementValuePairs, index);
3343
3344
if (!ALLOC_ARRAY(annotationList[i].elementValuePairs, annotationList[i].numberOfElementValuePairs, J9CfrAnnotationElementPair)) {
3345
return BCT_ERR_OUT_OF_ROM;
3346
}
3347
3348
for (j = 0; j < annotationList[i].numberOfElementValuePairs; j++) {
3349
CHECK_EOF(2);
3350
NEXT_U16(annotationList[i].elementValuePairs[j].elementNameIndex, index);
3351
3352
result = readAnnotationElement(classfile, &annotationList[i].elementValuePairs[j].value,
3353
data, dataEnd, segment, segmentEnd, &index, &freePointer, flags);
3354
if (result != 0) {
3355
return result;
3356
}
3357
}
3358
}
3359
3360
*pIndex = index;
3361
*pFreePointer = freePointer;
3362
return 0;
3363
3364
_errorFound:
3365
return -1;
3366
}
3367
3368
/*
3369
Read one type_annotation attribute from the bytes in @data.
3370
Precondition: classfile reader is at the start of a type_annotation
3371
Postcondition: classfile reader is at the byte following the end of a type_annotation
3372
@return 0 on success, negative on failure
3373
*/
3374
3375
static I_32
3376
readTypeAnnotation(J9CfrClassFile * classfile, J9CfrTypeAnnotation * tAnn, U_8 * data,
3377
U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags)
3378
{
3379
U_8 targetType = 0;
3380
U_8 *index = *pIndex;
3381
U_32 errorCode = 0; /* required by CHECK_EOF */
3382
U_32 offset = 0; /* required by CHECK_EOF */
3383
U_32 i = 0;
3384
I_32 result = 0;
3385
U_8 *freePointer = *pFreePointer;
3386
3387
CHECK_EOF(1);
3388
NEXT_U8(targetType, index);
3389
tAnn->targetType = targetType;
3390
Trc_BCU_TypeAnnotation(targetType);
3391
switch (targetType) { /* use values from the JVM spec. Java SE 8 Edition, table 4.7.20-A&B */
3392
case CFR_TARGET_TYPE_TypeParameterGenericClass:
3393
case CFR_TARGET_TYPE_TypeParameterGenericMethod: {
3394
J9CfrTypeParameterTarget *t = &(tAnn->targetInfo.typeParameterTarget);
3395
CHECK_EOF(1);
3396
NEXT_U8(t->typeParameterIndex, index);
3397
};
3398
break;
3399
3400
case CFR_TARGET_TYPE_TypeInExtends: {
3401
J9CfrSupertypeTarget *t = &(tAnn->targetInfo.supertypeTarget);
3402
CHECK_EOF(2);
3403
NEXT_U16(t->supertypeIndex, index);
3404
}
3405
break;
3406
3407
case CFR_TARGET_TYPE_TypeInBoundOfGenericClass:
3408
case CFR_TARGET_TYPE_TypeInBoundOfGenericMethod: {
3409
J9CfrTypeParameterBoundTarget *t = &(tAnn->targetInfo.typeParameterBoundTarget);
3410
CHECK_EOF(2);
3411
NEXT_U8(t->typeParameterIndex, index);
3412
NEXT_U8(t->boundIndex, index);
3413
}
3414
break;
3415
3416
case CFR_TARGET_TYPE_TypeInFieldDecl:
3417
case CFR_TARGET_TYPE_ReturnType:
3418
case CFR_TARGET_TYPE_ReceiverType: /* empty_target */
3419
break;
3420
3421
case CFR_TARGET_TYPE_TypeInFormalParam: {
3422
J9CfrMethodFormalParameterTarget *t = &(tAnn->targetInfo.methodFormalParameterTarget);
3423
CHECK_EOF(1);
3424
NEXT_U8(t->formalParameterIndex, index);
3425
};
3426
break;
3427
3428
case CFR_TARGET_TYPE_TypeInThrows: {
3429
J9CfrThrowsTarget *t = &(tAnn->targetInfo.throwsTarget);
3430
CHECK_EOF(2);
3431
NEXT_U16(t->throwsTypeIndex, index);
3432
}
3433
break;
3434
3435
case CFR_TARGET_TYPE_TypeInLocalVar:
3436
case CFR_TARGET_TYPE_TypeInResourceVar: {
3437
U_32 ti;
3438
J9CfrLocalvarTarget *t = &(tAnn->targetInfo.localvarTarget);
3439
CHECK_EOF(2);
3440
NEXT_U16(t->tableLength, index);
3441
if (!ALLOC_ARRAY(t->table, t->tableLength, J9CfrLocalvarTargetEntry)) {
3442
return -2;
3443
}
3444
for (ti=0; ti < t->tableLength; ++ti) {
3445
J9CfrLocalvarTargetEntry *te = &(t->table[ti]);
3446
CHECK_EOF(6);
3447
NEXT_U16(te->startPC, index);
3448
NEXT_U16(te->length, index);
3449
NEXT_U16(te->index, index);
3450
}
3451
};
3452
break;
3453
case CFR_TARGET_TYPE_TypeInExceptionParam: {
3454
J9CfrCatchTarget *t = &(tAnn->targetInfo.catchTarget);
3455
CHECK_EOF(2);
3456
NEXT_U16(t->exceptiontableIndex, index);
3457
}
3458
break;
3459
3460
case CFR_TARGET_TYPE_TypeInInstanceof:
3461
case CFR_TARGET_TYPE_TypeInNew:
3462
case CFR_TARGET_TYPE_TypeInMethodrefNew:
3463
case CFR_TARGET_TYPE_TypeInMethodrefIdentifier: {
3464
J9CfrOffsetTarget *t = &(tAnn->targetInfo.offsetTarget);
3465
CHECK_EOF(2);
3466
NEXT_U16(t->offset, index);
3467
}
3468
break;
3469
3470
case CFR_TARGET_TYPE_TypeInCast:
3471
case CFR_TARGET_TYPE_TypeForGenericConstructorInNew:
3472
case CFR_TARGET_TYPE_TypeForGenericMethodInvocation:
3473
case CFR_TARGET_TYPE_TypeForGenericConstructorInMethodRef:
3474
case CFR_TARGET_TYPE_TypeForGenericMethodInvocationInMethodRef: {
3475
J9CfrTypeArgumentTarget *t = &(tAnn->targetInfo.typeArgumentTarget);
3476
CHECK_EOF(3);
3477
NEXT_U16(t->offset, index);
3478
NEXT_U8(t->typeArgumentIndex, index);
3479
}
3480
break;
3481
3482
default:
3483
errorCode = J9NLS_CFR_ERR_BAD_TARGET_TYPE_TAG;
3484
offset = (U_32) (index - data - 1);
3485
goto _errorFound;
3486
}
3487
3488
/* now parse the target_path */
3489
CHECK_EOF(1);
3490
NEXT_U8(tAnn->typePath.pathLength, index);
3491
if (!ALLOC_ARRAY(tAnn->typePath.path, tAnn->typePath.pathLength, J9CfrTypePathEntry)) {
3492
return -2;
3493
}
3494
for (i=0; i < tAnn->typePath.pathLength; ++i) {
3495
J9CfrTypePathEntry *entry = &tAnn->typePath.path[i];
3496
CHECK_EOF(2);
3497
NEXT_U8(entry->typePathKind, index);
3498
NEXT_U8(entry->typeArgumentIndex, index);
3499
}
3500
3501
/* read the annotation text */
3502
result = readAnnotations(classfile, &(tAnn->annotation), 1, data,
3503
dataEnd, segment, segmentEnd, &index, &freePointer, flags);
3504
*pFreePointer = freePointer;
3505
*pIndex = index;
3506
return result;
3507
3508
_errorFound:
3509
return BCT_ERR_INVALID_ANNOTATION;
3510
}
3511
3512
3513
/*
3514
Read the annotations from the bytes in @data.
3515
Returns 0 on success, non-zero on failure.
3516
*/
3517
3518
static I_32
3519
readAnnotationElement(J9CfrClassFile * classfile, J9CfrAnnotationElement ** pAnnotationElement, U_8 * data,
3520
U_8 * dataEnd, U_8 * segment, U_8 * segmentEnd, U_8 ** pIndex, U_8 ** pFreePointer, U_32 flags)
3521
{
3522
J9CfrAnnotationElement *element;
3523
U_8 *index = *pIndex; /* used by CHECK_EOF macro */
3524
U_8 *freePointer = *pFreePointer; /* used by ALLOC_* macros */
3525
J9CfrAnnotation *annotation;
3526
J9CfrAnnotationElementArray *array;
3527
J9CfrAnnotationElement **arrayWalk;
3528
U_32 errorCode, offset;
3529
U_32 j;
3530
I_32 result; /* used by ALLOC_* macros */
3531
U_32 annotationTag;
3532
3533
CHECK_EOF(1);
3534
NEXT_U8(annotationTag, index);
3535
3536
switch (annotationTag) {
3537
case 'B':
3538
case 'C':
3539
case 'D':
3540
case 'F':
3541
case 'I':
3542
case 'J':
3543
case 'S':
3544
case 'Z':
3545
case 's':
3546
/* primitive */
3547
if (!ALLOC_CAST(element, J9CfrAnnotationElementPrimitive, J9CfrAnnotationElement)) {
3548
return -2;
3549
}
3550
3551
CHECK_EOF(2);
3552
NEXT_U16(((J9CfrAnnotationElementPrimitive *)element)->constValueIndex, index);
3553
break;
3554
3555
case 'e':
3556
{
3557
J9CfrConstantPoolInfo* cpBase = classfile->constantPool;
3558
U_16 cpCount = classfile->constantPoolCount;
3559
U_16 typeNameIndex = 0;
3560
U_16 constNameIndex = 0;
3561
3562
if (!ALLOC_CAST(element, J9CfrAnnotationElementEnum, J9CfrAnnotationElement)) {
3563
return -2;
3564
}
3565
3566
CHECK_EOF(4);
3567
NEXT_U16(((J9CfrAnnotationElementEnum *)element)->typeNameIndex, index);
3568
NEXT_U16(((J9CfrAnnotationElementEnum *)element)->constNameIndex, index);
3569
3570
typeNameIndex = ((J9CfrAnnotationElementEnum *)element)->typeNameIndex;
3571
constNameIndex = ((J9CfrAnnotationElementEnum *)element)->constNameIndex;
3572
if ((0 == typeNameIndex) || (typeNameIndex >= cpCount) || (0 == constNameIndex) || (constNameIndex >= cpCount)) {
3573
return BCT_ERR_INVALID_ANNOTATION_BAD_CP_INDEX_OUT_OF_RANGE;
3574
}
3575
if ((CFR_CONSTANT_Utf8 != cpBase[typeNameIndex].tag) || (CFR_CONSTANT_Utf8 != cpBase[constNameIndex].tag)) {
3576
return BCT_ERR_INVALID_ANNOTATION_BAD_CP_UTF8_STRING;
3577
}
3578
break;
3579
}
3580
case 'c':
3581
if (!ALLOC_CAST(element, J9CfrAnnotationElementClass, J9CfrAnnotationElement)) {
3582
return -2;
3583
}
3584
3585
CHECK_EOF(2);
3586
NEXT_U16(((J9CfrAnnotationElementClass *)element)->classInfoIndex, index);
3587
break;
3588
3589
case '@':
3590
if (!ALLOC_CAST(element, J9CfrAnnotationElementAnnotation, J9CfrAnnotationElement)) {
3591
return -2;
3592
}
3593
3594
annotation = &((J9CfrAnnotationElementAnnotation *)element)->annotationValue;
3595
3596
result = readAnnotations(classfile, annotation, 1, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags);
3597
if (BCT_ERR_NO_ERROR != result) {
3598
return result;
3599
}
3600
3601
break;
3602
3603
case '[':
3604
if (!ALLOC_CAST(element, J9CfrAnnotationElementArray, J9CfrAnnotationElement)) {
3605
return -2;
3606
}
3607
array = (J9CfrAnnotationElementArray *)element;
3608
3609
CHECK_EOF(2);
3610
NEXT_U16(array->numberOfValues, index);
3611
3612
if (!ALLOC_ARRAY(array->values, array->numberOfValues, J9CfrAnnotationElement *)) {
3613
return -2;
3614
}
3615
3616
arrayWalk = array->values;
3617
for (j = 0; j < array->numberOfValues; j++, arrayWalk++) {
3618
result = readAnnotationElement(classfile, arrayWalk, data, dataEnd, segment, segmentEnd, &index, &freePointer, flags);
3619
if (result != 0) {
3620
return result;
3621
}
3622
}
3623
3624
break;
3625
3626
default:
3627
/* error */
3628
errorCode = J9NLS_CFR_ERR_BAD_ANNOTATION_TAG__ID;
3629
offset = (U_32) (index - data - 1);
3630
goto _errorFound;
3631
}
3632
3633
element->tag = annotationTag;
3634
3635
*pAnnotationElement = element;
3636
*pIndex = index;
3637
*pFreePointer = freePointer;
3638
return 0;
3639
3640
_errorFound:
3641
return BCT_ERR_INVALID_ANNOTATION;
3642
}
3643
3644
static VMINLINE U_16
3645
getUTF8Length(J9CfrConstantPoolInfo* constantPool, U_16 cpIndex)
3646
{
3647
return (U_16) constantPool[cpIndex].slot1;
3648
}
3649
3650
static VMINLINE U_8*
3651
getUTF8Data(J9CfrConstantPoolInfo* constantPool, U_16 cpIndex)
3652
{
3653
return constantPool[cpIndex].bytes;
3654
}
3655
3656
static IDATA
3657
compareMethodIDs(J9CfrConstantPoolInfo* constantPool, J9CfrMethod *a, J9CfrMethod *b)
3658
{
3659
U_16 aNameIndex = a->nameIndex;
3660
U_16 bNameIndex = b->nameIndex;
3661
U_16 aSigIndex = a->descriptorIndex;
3662
U_16 bSigIndex = b->descriptorIndex;
3663
U_8 *aNameData = getUTF8Data(constantPool, aNameIndex);
3664
U_8 *bNameData = getUTF8Data(constantPool, bNameIndex);
3665
U_8 *aSigData = getUTF8Data(constantPool, aSigIndex);
3666
U_8 *bSigData = getUTF8Data(constantPool, bSigIndex);
3667
U_16 aNameLength = getUTF8Length(constantPool, aNameIndex);
3668
U_16 bNameLength = getUTF8Length(constantPool, bNameIndex);
3669
U_16 aSigLength = getUTF8Length(constantPool, aSigIndex);
3670
U_16 bSigLength = getUTF8Length(constantPool, bSigIndex);
3671
3672
return compareMethodNameAndSignature(aNameData, aNameLength, aSigData, aSigLength, bNameData, bNameLength, bSigData, bSigLength);
3673
}
3674
3675
/**
3676
* Quicksort the list of methods, via one level of indirection: the array of structs is
3677
* unsorted, but the pointers to the struct are in sorted order. This function assumes all
3678
* items in the list are unique, and start come before end
3679
*
3680
* @param constantPool class constant pool
3681
* @param Vector of pointers to method descriptors
3682
* @start index of the first element to be sorted
3683
* @end index of the last element to be sorted
3684
*/
3685
static void
3686
sortMethodIndex(J9CfrConstantPoolInfo* constantPool, J9CfrMethod *list, IDATA start, IDATA end)
3687
{
3688
IDATA scanUp = start;
3689
IDATA scanDown = end;
3690
IDATA result = 0;
3691
J9CfrMethod pivot = list[(start+end)/2];
3692
3693
do {
3694
while (scanUp < scanDown) {
3695
result = compareMethodIDs(constantPool, &pivot, &list[scanUp]);
3696
if (result <= 0) {
3697
break;
3698
}
3699
scanUp += 1;
3700
}
3701
while (scanUp < scanDown) {
3702
result = compareMethodIDs(constantPool, &pivot, &list[scanDown]);
3703
if (result >= 0) {
3704
break;
3705
}
3706
scanDown -= 1;
3707
}
3708
if (scanUp < scanDown) {
3709
J9CfrMethod swap = list[scanDown];
3710
list[scanDown] = list[scanUp];
3711
list[scanUp] = swap;
3712
}
3713
} while (scanUp < scanDown);
3714
/*
3715
* invariant: scanUp == scanDown
3716
* invariant: result contains the comparison of the value at scanUp
3717
* invariant: if scanUp == end, the entire list, with the possible exception of the last element, is less than or equal to the pivot
3718
* invariant: everything from scanUp+1 and up is greater than the pivot value
3719
* the value at scanUp may be greater, less, or same as the pivot
3720
*/
3721
Trc_BCU_Assert_Equals(scanUp, scanDown);
3722
if ((end - start) >= 2) { /* list of length 1 or 2 is already sorted */
3723
if (result <= 0) { /* scanUp value is greater than or equal to pivot */
3724
scanUp -= 1;
3725
}
3726
if (result >= 0) { /* scanUp value is less than or equal to pivot */
3727
scanDown += 1;
3728
}
3729
if (scanUp > start) {
3730
sortMethodIndex(constantPool, list, start, scanUp);
3731
}
3732
if (scanDown < end) {
3733
sortMethodIndex(constantPool, list, scanDown, end);
3734
}
3735
}
3736
}
3737
3738
#if JAVA_SPEC_VERSION >= 15
3739
I_32
3740
checkClassBytes(J9VMThread *currentThread, U_8* classBytes, UDATA classBytesLength, U_8* segment, U_32 segmentLength)
3741
{
3742
I_32 rc = 0;
3743
U_32 cfrFlags = BCT_JavaMaxMajorVersionShifted | BCT_AnyPreviewVersion | BCT_BasicCheckOnly;
3744
PORT_ACCESS_FROM_VMC(currentThread);
3745
if (NULL != classBytes) {
3746
rc = j9bcutil_readClassFileBytes(PORTLIB, NULL, classBytes, classBytesLength, segment, segmentLength, cfrFlags, NULL, NULL, 0, 0);
3747
}
3748
return rc;
3749
}
3750
#endif /* JAVA_SPEC_VERSION >= 15 */
3751
3752
3753