Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcverify/vrfyhelp.c
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 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 "bcvcfr.h"
24
#include "bcverify.h"
25
#include "bcverify_internal.h"
26
#include "cfreader.h"
27
#include "j9protos.h"
28
#include "j9consts.h"
29
#include "vrfyconvert.h"
30
#include "j9cp.h"
31
#include "j9bcvnls.h"
32
#include "rommeth.h"
33
#include "ut_j9bcverify.h"
34
35
#define SUPERCLASS(clazz) ((clazz)->superclasses[ J9CLASS_DEPTH(clazz) - 1 ])
36
#define J9CLASS_INDEX_FROM_CLASS_ENTRY(clazz) ((clazz & BCV_CLASS_INDEX_MASK) >> BCV_CLASS_INDEX_SHIFT)
37
#define J9CLASS_ARITY_FROM_CLASS_ENTRY(clazz) (((clazz & BCV_ARITY_MASK) >> BCV_ARITY_SHIFT) + ((clazz & BCV_TAG_BASE_ARRAY_OR_NULL) >> 1))
38
39
#define CLONEABLE_CLASS_NAME "java/lang/Cloneable"
40
#define SERIALIZEABLE_CLASS_NAME "java/io/Serializable"
41
#define CLONEABLE_CLASS_NAME_LENGTH (sizeof(CLONEABLE_CLASS_NAME) - 1)
42
#define SERIALIZEABLE_CLASS_NAME_LENGTH (sizeof(SERIALIZEABLE_CLASS_NAME) - 1)
43
44
static VMINLINE UDATA compareTwoUTF8s (J9UTF8 * first, J9UTF8 * second);
45
static UDATA addClassName (J9BytecodeVerificationData * verifyData, U_8 * name, UDATA length, UDATA index);
46
static void getNameAndLengthFromClassNameList (J9BytecodeVerificationData *verifyData, UDATA listIndex, U_8 ** name, UDATA * length);
47
static IDATA findFieldFromRamClass (J9Class ** ramClass, J9ROMFieldRef * field, UDATA firstSearch);
48
static IDATA findMethodFromRamClass (J9BytecodeVerificationData * verifyData, J9Class ** ramClass, J9ROMNameAndSignature * method, UDATA firstSearch);
49
static VMINLINE UDATA * pushType (J9BytecodeVerificationData *verifyData, U_8 * signature, UDATA * stackTop);
50
static IDATA isRAMClassCompatible(J9BytecodeVerificationData *verifyData, U_8* parentClass, UDATA parentLength, U_8* childClass, UDATA childLength, IDATA *reasonCode);
51
52
J9_DECLARE_CONSTANT_UTF8(j9_vrfy_Object, "java/lang/Object");
53
J9_DECLARE_CONSTANT_UTF8(j9_vrfy_String, "java/lang/String");
54
J9_DECLARE_CONSTANT_UTF8(j9_vrfy_Throwable, "java/lang/Throwable");
55
J9_DECLARE_CONSTANT_UTF8(j9_vrfy_Class, "java/lang/Class");
56
J9_DECLARE_CONSTANT_UTF8(j9_vrfy_MethodType, "java/lang/invoke/MethodType");
57
J9_DECLARE_CONSTANT_UTF8(j9_vrfy_MethodHandle, "java/lang/invoke/MethodHandle");
58
59
60
/* return the new index in the class list table for this name, add it if missing
61
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
62
*/
63
static UDATA
64
addClassName(J9BytecodeVerificationData * verifyData, U_8 * name, UDATA length, UDATA index)
65
{
66
J9ROMClass * romClass = verifyData->romClass;
67
U_32 *offset;
68
J9UTF8 *utf8;
69
UDATA classNameInClass = TRUE;
70
UDATA newSize, i, delta;
71
U_8 *newBuffer;
72
PORT_ACCESS_FROM_PORT(verifyData->portLib);
73
74
/* grow the buffers if necessary - will ask for an always conservative amount - assumes classNameInClass = FALSE */
75
if ((verifyData->classNameSegmentFree + sizeof(UDATA) + sizeof(J9UTF8) + length + sizeof(UDATA)) >= verifyData->classNameSegmentEnd) {
76
/* Do some magic to grow the classNameSegment. */
77
newSize = (UDATA) (((length + sizeof(UDATA) + sizeof(J9UTF8) + sizeof(UDATA)) < (32 * (sizeof(UDATA) + sizeof(J9UTF8))))
78
? (32 * (sizeof(UDATA) + sizeof(J9UTF8)))
79
: (length + sizeof(UDATA) + sizeof(J9UTF8) + sizeof(UDATA) - 1) & ~(sizeof(UDATA) - 1));
80
delta = (UDATA) (verifyData->classNameSegmentFree - verifyData->classNameSegment);
81
newSize += verifyData->classNameSegmentEnd - verifyData->classNameSegment;
82
newBuffer = j9mem_allocate_memory( newSize , J9MEM_CATEGORY_CLASSES);
83
if( !newBuffer ) {
84
return BCV_ERR_INSUFFICIENT_MEMORY; /* fail */
85
}
86
verifyData->classNameSegmentFree = newBuffer + delta;
87
memcpy( newBuffer, verifyData->classNameSegment, (UDATA) (verifyData->classNameSegmentEnd - verifyData->classNameSegment) );
88
delta = (UDATA) ((newBuffer - verifyData->classNameSegment) / sizeof (J9UTF8));
89
bcvfree( verifyData, verifyData->classNameSegment );
90
/* adjust the classNameList for the moved strings */
91
i = 0;
92
while (verifyData->classNameList[i]) {
93
/* Second pass verification can have new strings and preverify data references - move only the new string references */
94
if (((U_8 *)(verifyData->classNameList[i]) >= verifyData->classNameSegment) && ((U_8 *)(verifyData->classNameList[i]) < verifyData->classNameSegmentEnd)) {
95
verifyData->classNameList[i] += delta;
96
}
97
i++;
98
}
99
verifyData->classNameSegment = newBuffer;
100
verifyData->classNameSegmentEnd = newBuffer + newSize;
101
}
102
103
if (&(verifyData->classNameList[index + 1]) >= verifyData->classNameListEnd) {
104
/* Do some magic to grow the classNameList. */
105
newSize = (UDATA) ((U_8 *) verifyData->classNameListEnd - (U_8 *) verifyData->classNameList + (32 * sizeof(UDATA)));
106
newBuffer = j9mem_allocate_memory( newSize , J9MEM_CATEGORY_CLASSES);
107
if( !newBuffer ) {
108
return BCV_ERR_INSUFFICIENT_MEMORY; /* fail */
109
}
110
memcpy( newBuffer, (U_8*) verifyData->classNameList, (UDATA) (((U_8*) verifyData->classNameListEnd) - ((U_8*) verifyData->classNameList)) );
111
bcvfree( verifyData, verifyData->classNameList );
112
verifyData->classNameList = (J9UTF8 **) newBuffer;
113
verifyData->classNameListEnd = (J9UTF8 **) (newBuffer + newSize);
114
}
115
116
/* Is the new name found in the ROM class? */
117
if (((UDATA) name < (UDATA) romClass) || ((UDATA) name >= ((UDATA) romClass + (UDATA) romClass->romSize))) {
118
classNameInClass = FALSE;
119
}
120
121
offset = (U_32 *) verifyData->classNameSegmentFree;
122
utf8 = (J9UTF8 *) (offset + 1);
123
J9UTF8_SET_LENGTH(utf8, (U_16) length);
124
verifyData->classNameSegmentFree += sizeof(U_32);
125
if (classNameInClass) {
126
offset[0] = (U_32) ((UDATA) name - (UDATA) romClass);
127
verifyData->classNameSegmentFree += sizeof(U_32);
128
} else {
129
offset[0] = 0;
130
strncpy((char *) J9UTF8_DATA(utf8), (char *) name, length);
131
verifyData->classNameSegmentFree += (sizeof(J9UTF8) + length + sizeof(U_32) - 1) & ~(sizeof(U_32) - 1); /* next U_32 boundary */
132
}
133
verifyData->classNameList[index] = (J9UTF8 *) offset;
134
verifyData->classNameList[index + 1] = NULL;
135
136
137
return index;
138
}
139
140
141
142
/* Return the new index in the class list table for this name, add it if missing */
143
144
UDATA
145
findClassName(J9BytecodeVerificationData * verifyData, U_8 * name, UDATA length)
146
{
147
J9ROMClass * romClass = verifyData->romClass;
148
U_32 *offset = NULL;
149
U_8 *data = NULL;
150
J9UTF8 *utf8 = NULL;
151
UDATA index = 0;
152
153
154
155
while ((offset = (U_32 *) verifyData->classNameList[index]) != NULL) {
156
utf8 = (J9UTF8 *) (offset + 1);
157
if ((UDATA) J9UTF8_LENGTH(utf8) == length) {
158
data = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);
159
160
/* check for identical pointers */
161
if (data == name) {
162
return index;
163
}
164
165
/* handle names found not in the romClass, but in the classNameSegment only */
166
if (0 == offset[0]) {
167
data = J9UTF8_DATA(utf8);
168
}
169
170
if (0 == memcmp(data, name, length)) {
171
return index;
172
}
173
174
}
175
index++;
176
}
177
178
/* add a class name if not found */
179
return addClassName(verifyData, name, length, index);
180
}
181
182
/* Return the encoded stackmap type for the class. add class into class list table if missing */
183
184
UDATA
185
convertClassNameToStackMapType(J9BytecodeVerificationData * verifyData, U_8 *name, U_16 length, UDATA type, UDATA arity)
186
{
187
J9ROMClass * romClass = verifyData->romClass;
188
U_32 *offset = NULL;
189
U_8 *data = NULL;
190
J9UTF8 *utf8 = NULL;
191
J9UTF8 *utf8_p = NULL;
192
UDATA index = 0;
193
194
195
while ((offset = (U_32 *) verifyData->classNameList[index]) != NULL) {
196
utf8 = (J9UTF8 *) (offset + 1);
197
if ((UDATA) J9UTF8_LENGTH(utf8) == (UDATA)length) {
198
data = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);
199
200
/* check for identical pointers */
201
if (data == name) {
202
return type | (index << BCV_CLASS_INDEX_SHIFT);
203
}
204
205
/* handle names found not in the romClass, but in the classNameSegment only */
206
if (0 == offset[0]) {
207
data = J9UTF8_DATA(utf8);
208
}
209
210
if (0 == memcmp(data, name, (UDATA)length)) {
211
return type | (index << BCV_CLASS_INDEX_SHIFT);
212
}
213
214
}
215
index++;
216
}
217
218
/* add a class name if not found */
219
return type | (addClassName(verifyData, name, length, index) << BCV_CLASS_INDEX_SHIFT);
220
}
221
222
223
/**
224
* @returns BOOLEAN indicating if uninitializedThis is on the stack
225
*/
226
BOOLEAN
227
buildStackFromMethodSignature( J9BytecodeVerificationData *verifyData, UDATA **stackTopPtr, UDATA *argCount)
228
{
229
/* @romMethod is a pointer to a romMethod structure
230
@stackTop is a pointer to a pointer to the start of the stack (grows towards larger values)
231
232
The modified stack is the return result, stackTop is modified accordingly.
233
*/
234
const J9ROMClass *romClass = verifyData->romClass;
235
const J9ROMMethod *romMethod = verifyData->romMethod;
236
const UDATA argMax = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod);
237
UDATA i;
238
U_8 *args;
239
UDATA arity, baseType;
240
UDATA classIndex = 0;
241
UDATA *stackTop;
242
BOOLEAN isUninitializedThis = FALSE;
243
244
stackTop = *stackTopPtr;
245
*argCount = 0;
246
247
/* if this is a virtual method, push the receiver */
248
249
if ((!(romMethod->modifiers & J9AccStatic)) && (argMax > 0)) {
250
/* this is a virtual method, an object compatible with this class is on the stack */
251
J9UTF8* utf8string = J9ROMMETHOD_NAME(romMethod);
252
J9UTF8 *className = J9ROMCLASS_CLASSNAME(romClass);
253
254
classIndex = findClassName(verifyData, J9UTF8_DATA(className), J9UTF8_LENGTH(className));
255
256
/* In the <init> method of Object the type of this is Object. In other <init> methods, the type of this is uninitializedThis */
257
if ((J9UTF8_DATA(utf8string)[0] == '<') && (J9UTF8_DATA(utf8string)[1] == 'i') && (classIndex != BCV_JAVA_LANG_OBJECT_INDEX)) {
258
/* This is <init>, not java/lang/Object */
259
PUSH(BCV_SPECIAL_INIT | (classIndex << BCV_CLASS_INDEX_SHIFT));
260
isUninitializedThis = TRUE;
261
} else {
262
PUSH(BCV_GENERIC_OBJECT | (classIndex << BCV_CLASS_INDEX_SHIFT));
263
}
264
(*argCount)++;
265
}
266
267
/* Walk the signature of the method to determine the arg shape */
268
269
args = J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod));
270
271
for (i = 1; args[i] != ')'; i++) {
272
(*argCount)++;
273
if ((*argCount) > argMax) {
274
continue;
275
}
276
arity = 0;
277
while (args[i] == '[') {
278
i++;
279
arity++;
280
}
281
282
if (IS_REF_OR_VAL_SIGNATURE(args[i])) {
283
U_8 *string;
284
U_16 length = 0;
285
286
i++;
287
string = &args[i]; /* remember the start of the string */
288
while (args[i] != ';') {
289
i++;
290
length++;
291
}
292
classIndex = convertClassNameToStackMapType(verifyData, string, length, 0, arity);
293
PUSH(classIndex | (arity << BCV_ARITY_SHIFT));
294
} else {
295
if (arity) {
296
/* Base arrays have implicit arity of 1 */
297
arity--;
298
PUSH(BCV_TAG_BASE_ARRAY_OR_NULL | (UDATA) baseTypeCharConversion[args[i] - 'A'] | (arity << BCV_ARITY_SHIFT));
299
} else {
300
baseType = (UDATA) argTypeCharConversion[args[i] - 'A'];
301
PUSH(baseType);
302
if ((args[i] == 'J') || (args[i] == 'D')) {
303
(*argCount)++;
304
PUSH(BCV_BASE_TYPE_TOP);
305
}
306
}
307
}
308
}
309
310
for (i = 0; i < J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod); i++) {
311
/* Now push a bunch of uninitialized variables */
312
PUSH (BCV_BASE_TYPE_TOP);
313
}
314
*stackTopPtr = stackTop;
315
316
return isUninitializedThis;
317
}
318
319
320
UDATA*
321
pushReturnType(J9BytecodeVerificationData *verifyData, J9UTF8 * utf8string, UDATA * stackTop)
322
{
323
U_8 *signature;
324
325
/* TODO: Determine if faster to walk utf8string backwards to get the return type as
326
* there is only 1 return type and potentially many arg types: ie:
327
* (Ljava/lang/String;II)Ljava/lang/String; is fewer iterations if walking backwards
328
*
329
* signature = J9UTF8_DATA(utf8string) + length - 1;
330
* while (*signature-- != ')');
331
*/
332
333
signature = J9UTF8_DATA(utf8string);
334
while (*signature++ != ')');
335
336
return pushType(verifyData, signature, stackTop);
337
}
338
339
340
341
UDATA*
342
pushFieldType(J9BytecodeVerificationData *verifyData, J9UTF8 * utf8string, UDATA *stackTop)
343
{
344
return pushType(verifyData, J9UTF8_DATA(utf8string), stackTop);
345
}
346
347
348
349
350
UDATA *
351
pushClassType(J9BytecodeVerificationData * verifyData, J9UTF8 * utf8string, UDATA * stackTop)
352
{
353
if (J9UTF8_DATA(utf8string)[0] == '[') {
354
UDATA arrayType = parseObjectOrArrayName(verifyData, J9UTF8_DATA(utf8string));
355
PUSH(arrayType);
356
} else {
357
PUSH(convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string),J9UTF8_LENGTH(utf8string), BCV_OBJECT_OR_ARRAY, 0));
358
}
359
360
return stackTop;
361
}
362
363
364
365
void
366
initializeClassNameList(J9BytecodeVerificationData *verifyData)
367
{
368
J9UTF8 *name;
369
370
/* reset the pointer and zero terminate the class name list */
371
verifyData->classNameSegmentFree = verifyData->classNameSegment;
372
verifyData->classNameList[0] = NULL;
373
374
/* Add the "known" classes to the classNameList. The order
375
* here must exactly match the indexes as listed in bytecodewalk.h.
376
*/
377
378
/* BCV_JAVA_LANG_OBJECT_INDEX 0 */
379
name = (J9UTF8*)&j9_vrfy_Object;
380
findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));
381
/* BCV_JAVA_LANG_STRING_INDEX 1 */
382
name = (J9UTF8*)&j9_vrfy_String;
383
findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));
384
/* BCV_JAVA_LANG_THROWABLE_INDEX 2 */
385
name = (J9UTF8*)&j9_vrfy_Throwable;
386
findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));
387
/* BCV_JAVA_LANG_CLASS_INDEX 3 */
388
name = (J9UTF8*)&j9_vrfy_Class;
389
findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));
390
/* BCV_JAVA_LANG_INVOKE_METHOD_TYPE_INDEX 4 */
391
name = (J9UTF8*)&j9_vrfy_MethodType;
392
findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));
393
/* BCV_JAVA_LANG_INVOKE_METHODHANDLE_INDEX 5 */
394
name = (J9UTF8*)&j9_vrfy_MethodHandle;
395
findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));
396
}
397
398
399
UDATA *
400
pushLdcType(J9BytecodeVerificationData *verifyData, J9ROMClass * romClass, UDATA index, UDATA * stackTop)
401
{
402
switch(J9_CP_TYPE(J9ROMCLASS_CPSHAPEDESCRIPTION(romClass), index)) {
403
case J9CPTYPE_CLASS:
404
PUSH(BCV_JAVA_LANG_CLASS_INDEX << BCV_CLASS_INDEX_SHIFT);
405
break;
406
case J9CPTYPE_STRING:
407
PUSH(BCV_JAVA_LANG_STRING_INDEX << BCV_CLASS_INDEX_SHIFT);
408
break;
409
case J9CPTYPE_INT:
410
PUSH_INTEGER_CONSTANT;
411
break;
412
case J9CPTYPE_FLOAT:
413
PUSH_FLOAT_CONSTANT;
414
break;
415
case J9CPTYPE_METHOD_TYPE:
416
PUSH(BCV_JAVA_LANG_INVOKE_METHOD_TYPE_INDEX << BCV_CLASS_INDEX_SHIFT);
417
break;
418
case J9CPTYPE_METHODHANDLE:
419
PUSH(BCV_JAVA_LANG_INVOKE_METHODHANDLE_INDEX << BCV_CLASS_INDEX_SHIFT);
420
break;
421
case J9CPTYPE_CONSTANT_DYNAMIC:
422
{
423
J9ROMConstantDynamicRef* romConstantDynamicRef = (J9ROMConstantDynamicRef *)(J9_ROM_CP_FROM_ROM_CLASS(romClass) + index);
424
J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMCONSTANTDYNAMICREF_NAMEANDSIGNATURE(romConstantDynamicRef));
425
/* The signature referenced by a ConstantDynamic entry is a field descriptor */
426
stackTop = pushType(verifyData, J9UTF8_DATA(signature), stackTop);
427
}
428
break;
429
}
430
431
return stackTop;
432
}
433
434
435
436
/*
437
* NOTE:
438
* targetClass must be:
439
* - null
440
* - an object
441
* - an array of objects
442
* - an array of base types
443
* sourceClass can be any valid type descriptor, including NULL, base types, and special objects
444
*
445
* returns TRUE if class are compatible
446
* returns FALSE if class are NOT compatible
447
* isInterfaceClass() or isRAMClassCompatible() sets reasonCode to BCV_ERR_INSUFFICIENT_MEMORY in OOM
448
*/
449
450
IDATA
451
isClassCompatible(J9BytecodeVerificationData *verifyData, UDATA sourceClass, UDATA targetClass, IDATA *reasonCode)
452
{
453
UDATA sourceIndex, targetIndex;
454
UDATA sourceArity, targetArity;
455
IDATA rc;
456
U_8 *sourceName, *targetName;
457
UDATA sourceLength, targetLength;
458
459
/* Record class relationship if -XX:+ClassRelationshipVerifier is used */
460
BOOLEAN classRelationshipVerifierEnabled = J9_ARE_ANY_BITS_SET(verifyData->vmStruct->javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_CLASS_RELATIONSHIP_VERIFIER);
461
462
*reasonCode = 0;
463
464
/* if they are identical, then we're done */
465
if( sourceClass == targetClass ) {
466
return (IDATA) TRUE;
467
}
468
469
/* NULL is magically compatible */
470
if( sourceClass == BCV_BASE_TYPE_NULL ) {
471
return (IDATA) TRUE;
472
}
473
474
/* Covers the following cases:
475
* 1) Objects are not compatible with base types
476
* 2) uninitialized(x) can only merge to itself (covered by srcClass == trgClass check)
477
* 3) uninitialized_this can only merge to itself (covered by srcClass == trgClass check)
478
*/
479
if( sourceClass & BCV_BASE_OR_SPECIAL ) {
480
return (IDATA) FALSE;
481
}
482
483
/* if the target is java/lang/Object, we're done */
484
if( targetClass == (BCV_JAVA_LANG_OBJECT_INDEX << BCV_CLASS_INDEX_SHIFT) ) {
485
return (IDATA) TRUE;
486
}
487
488
/* only NULL is compatible with NULL */
489
if ( targetClass == BCV_BASE_TYPE_NULL ) {
490
return (IDATA) FALSE;
491
}
492
493
sourceArity = J9CLASS_ARITY_FROM_CLASS_ENTRY(sourceClass);
494
targetArity = J9CLASS_ARITY_FROM_CLASS_ENTRY(targetClass);
495
496
/* You can't cast to a larger arity */
497
if( targetArity > sourceArity ) {
498
return (IDATA) FALSE;
499
}
500
501
/* load up the indices, but be aware that these might be base type arrays */
502
sourceIndex = J9CLASS_INDEX_FROM_CLASS_ENTRY(sourceClass);
503
targetIndex = J9CLASS_INDEX_FROM_CLASS_ENTRY(targetClass);
504
505
if( targetArity < sourceArity ) {
506
/* if target is an interface, or an object -- but we need to make sure its not a base type array */
507
if (targetClass & BCV_TAG_BASE_ARRAY_OR_NULL) {
508
return (IDATA) FALSE;
509
}
510
511
if (targetIndex == BCV_JAVA_LANG_OBJECT_INDEX) {
512
return (IDATA) TRUE;
513
}
514
515
getNameAndLengthFromClassNameList (verifyData, targetIndex, &targetName, &targetLength);
516
517
/* Jazz 109803: Java 8 VM Spec at 4.10.1.2 Verification Type System says:
518
* For assignments, interfaces are treated like Object.
519
* isJavaAssignable(class(_, _), class(To, L)) :- loadedClass(To, L, ToClass), classIsInterface(ToClass).
520
* isJavaAssignable(From, To) :- isJavaSubclassOf(From, To).
521
*
522
* Array types are subtypes of Object. The intent is also that array types
523
* are subtypes of Cloneable and java.io.Serializable.
524
* isJavaAssignable(arrayOf(_), class('java/lang/Object', BL)) :- isBootstrapLoader(BL).
525
* isJavaAssignable(arrayOf(_), X) :- isArrayInterface(X).
526
* isArrayInterface(class('java/lang/Cloneable', BL)) :- isBootstrapLoader(BL).
527
* isArrayInterface(class('java/io/Serializable', BL)) :- isBootstrapLoader(BL).
528
*
529
* According to the statements above, it emphasizes two cases from the code perspective:
530
* 1) if the arity of both sourceClass and targetClass is 0,
531
* then targetClass (ToClass) should be an interface for compatibility.
532
* 2) if not the case and sourceClass is an array type (sourceArity > 0),
533
* array type can't be assigned to arbitrary interface or array of interface
534
* except Object (already checked above), java/lang/Cloneable and java/io/Serializable,
535
* which means targetClass must be one/array of Object, java/lang/Cloneable and java/io/Serializable.
536
*/
537
if (J9UTF8_DATA_EQUALS(targetName, targetLength, CLONEABLE_CLASS_NAME, CLONEABLE_CLASS_NAME_LENGTH)
538
|| J9UTF8_DATA_EQUALS(targetName, targetLength, SERIALIZEABLE_CLASS_NAME, SERIALIZEABLE_CLASS_NAME_LENGTH)
539
) {
540
rc = isInterfaceClass(verifyData, targetName, targetLength, reasonCode);
541
542
if ((classRelationshipVerifierEnabled) && (BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED == *reasonCode)) {
543
getNameAndLengthFromClassNameList (verifyData, sourceIndex, &sourceName, &sourceLength);
544
rc = j9bcv_recordClassRelationship (verifyData->vmStruct, verifyData->classLoader, sourceName, sourceLength, targetName, targetLength, reasonCode);
545
}
546
547
return rc;
548
}
549
550
return (IDATA) FALSE;
551
}
552
553
/* At this point we know the arity is equal -- see if either is a base type array */
554
if( (sourceClass & BCV_TAG_BASE_ARRAY_OR_NULL) || (targetClass & BCV_TAG_BASE_ARRAY_OR_NULL) ) {
555
/* then they should have been identical, so fail */
556
return (IDATA) FALSE;
557
}
558
559
if (targetIndex == BCV_JAVA_LANG_OBJECT_INDEX) {
560
return (IDATA) TRUE;
561
}
562
563
getNameAndLengthFromClassNameList (verifyData, targetIndex, &targetName, &targetLength);
564
565
/* if the target is an interface, be permissive */
566
rc = isInterfaceClass(verifyData, targetName, targetLength, reasonCode);
567
568
getNameAndLengthFromClassNameList (verifyData, sourceIndex, &sourceName, &sourceLength);
569
570
/* classRelationshipVerifierEnabled and target not already loaded, so record the class relationship */
571
if ((classRelationshipVerifierEnabled) && (BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED == *reasonCode)) {
572
rc = j9bcv_recordClassRelationship(verifyData->vmStruct, verifyData->classLoader, sourceName, sourceLength, targetName, targetLength, reasonCode);
573
}
574
575
if ((IDATA) FALSE != rc) {
576
return rc;
577
}
578
579
if (NULL != verifyData->vmStruct->currentException) {
580
return (IDATA) FALSE;
581
}
582
583
if (J9ROMCLASS_IS_HIDDEN(verifyData->romClass)) {
584
J9UTF8* className = J9ROMCLASS_CLASSNAME(verifyData->romClass);
585
if (J9UTF8_DATA_EQUALS(J9UTF8_DATA(className), J9UTF8_LENGTH(className), sourceName, sourceLength)) {
586
/* isRAMClassCompatible() cannot find ram class of a hidden class, we are testing if
587
* the source class is the subclass of target class. We can use superclass of source class instead here.
588
* A hidden class can not be super class of another class, the hidden class name it is not findable and its name is generated at runtime.
589
*/
590
J9UTF8* superClassName = J9ROMCLASS_SUPERCLASSNAME(verifyData->romClass);
591
sourceLength = J9UTF8_LENGTH(superClassName);
592
sourceName = J9UTF8_DATA(superClassName);
593
}
594
}
595
596
rc = isRAMClassCompatible(verifyData, targetName, targetLength , sourceName, sourceLength, reasonCode);
597
598
/* classRelationshipVerifierEnabled and source and/or target not already loaded, so record the class relationship */
599
if ((classRelationshipVerifierEnabled) && (BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED == *reasonCode)) {
600
rc = j9bcv_recordClassRelationship(verifyData->vmStruct, verifyData->classLoader, sourceName, sourceLength, targetName, targetLength, reasonCode);
601
}
602
603
return rc;
604
}
605
606
/*
607
API
608
@verifyData - internal data structure
609
@parentClass - U_8 pointer to parent class name
610
@parentLength - UDATA length of parent class name
611
@childClass - U_8 pointer to child class name
612
@childLength - UDATA length of child class name
613
614
If the parentClass is not a super class of the child class, answer FALSE, otherwise answer TRUE.
615
When FALSE, reasonCode (set by j9rtv_verifierGetRAMClass) is
616
BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case
617
618
619
*/
620
static IDATA
621
isRAMClassCompatible(J9BytecodeVerificationData *verifyData, U_8* parentClass, UDATA parentLength, U_8* childClass, UDATA childLength, IDATA *reasonCode)
622
{
623
J9Class *sourceRAMClass, *targetRAMClass;
624
625
/* Go get the ROM class for the source and target */
626
targetRAMClass = j9rtv_verifierGetRAMClass( verifyData, verifyData->classLoader, parentClass, parentLength, reasonCode );
627
if (NULL == targetRAMClass) {
628
return FALSE;
629
}
630
631
/* if the target is an interface, be permissive */
632
if( targetRAMClass->romClass->modifiers & J9AccInterface ) {
633
return (IDATA) TRUE;
634
}
635
636
sourceRAMClass = j9rtv_verifierGetRAMClass( verifyData, verifyData->classLoader, childClass, childLength, reasonCode );
637
if (NULL == sourceRAMClass) {
638
return FALSE;
639
}
640
641
targetRAMClass = J9_CURRENT_CLASS(targetRAMClass);
642
return isSameOrSuperClassOf( targetRAMClass, sourceRAMClass );
643
}
644
645
646
/*
647
API
648
@verifyData - internal data structure
649
@className - U_8 pointer to class name
650
@classLength - UDATA length of class name
651
652
If class is an interface answer TRUE, otherwise answer FALSE.
653
When FALSE, reasonCode (set by j9rtv_verifierGetRAMClass) is
654
BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case
655
656
657
*/
658
IDATA
659
isInterfaceClass(J9BytecodeVerificationData * verifyData, U_8* className, UDATA classLength, IDATA *reasonCode)
660
{
661
J9Class *ramClass;
662
663
*reasonCode = 0;
664
665
ramClass = j9rtv_verifierGetRAMClass(verifyData, verifyData->classLoader, className, classLength, reasonCode);
666
if (NULL == ramClass) {
667
return FALSE;
668
}
669
670
/* if the target is an interface, be permissive */
671
if (ramClass->romClass->modifiers & J9AccInterface) {
672
return TRUE;
673
}
674
675
return FALSE;
676
}
677
678
679
static UDATA *
680
pushType(J9BytecodeVerificationData *verifyData, U_8 * signature, UDATA * stackTop)
681
{
682
if (*signature != 'V') {
683
if ((*signature == '[') || IS_REF_OR_VAL_SIGNATURE(*signature)) {
684
PUSH(parseObjectOrArrayName(verifyData, signature));
685
} else {
686
UDATA baseType = (UDATA) argTypeCharConversion[*signature - 'A'];
687
PUSH(baseType);
688
if ((*signature == 'J') || (*signature == 'D')) {
689
PUSH(BCV_BASE_TYPE_TOP);
690
}
691
}
692
}
693
694
return stackTop;
695
}
696
697
698
699
/*
700
* decode the 'special' type described by type, and answer it's normal type.
701
* If type is not a NEW or INIT object, return type unchanged
702
*/
703
704
UDATA
705
getSpecialType(J9BytecodeVerificationData *verifyData, UDATA type, U_8* bytecodes)
706
{
707
J9ROMClass * romClass = verifyData->romClass;
708
J9UTF8* newClassUTF8;
709
710
/* verify that this is a NEW object */
711
if ((type & BCV_SPECIAL_NEW) == (UDATA) (BCV_SPECIAL_NEW)) {
712
/* Lookup the Class from the cpEntry used in the 'JBnew' bytecode */
713
U_8* bcTempPtr;
714
U_16 index;
715
J9ROMConstantPoolItem* constantPool;
716
717
bcTempPtr = bytecodes + ((type & BCV_CLASS_INDEX_MASK) >> BCV_CLASS_INDEX_SHIFT);
718
719
index = PARAM_16(bcTempPtr, 1);
720
721
constantPool = (J9ROMConstantPoolItem *) ((U_8 *) romClass + sizeof(J9ROMClass));
722
newClassUTF8 = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) (&constantPool[index]));
723
} else {
724
/* verify that this is an INIT object and un-tag it */
725
if ((type & BCV_SPECIAL_INIT) == (UDATA) (BCV_SPECIAL_INIT)) {
726
newClassUTF8 = J9ROMCLASS_CLASSNAME(romClass);
727
} else {
728
return type;
729
}
730
}
731
732
return convertClassNameToStackMapType(verifyData, J9UTF8_DATA(newClassUTF8), J9UTF8_LENGTH(newClassUTF8), 0, 0);
733
}
734
735
736
/*
737
* Validates classes compatibility by their name
738
*
739
* returns TRUE if class are compatible
740
* returns FALSE it not compatible
741
* reasonCode (set by isClassCompatible) is:
742
* BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case
743
*/
744
IDATA
745
isClassCompatibleByName(J9BytecodeVerificationData *verifyData, UDATA sourceClass, U_8* targetClassName, UDATA targetClassNameLength, IDATA *reasonCode)
746
{
747
UDATA index;
748
749
*reasonCode = 0;
750
751
/* NULL is magically compatible */
752
if( sourceClass == BCV_BASE_TYPE_NULL )
753
return (IDATA) TRUE;
754
755
/* If the source is special, or a base type -- fail */
756
if( sourceClass & BCV_BASE_OR_SPECIAL )
757
return (IDATA) FALSE;
758
759
if (*targetClassName == '[') {
760
index = parseObjectOrArrayName(verifyData, targetClassName);
761
} else {
762
index = convertClassNameToStackMapType(verifyData, targetClassName, (U_16)targetClassNameLength, 0, 0);
763
}
764
765
return isClassCompatible(verifyData, sourceClass, index, reasonCode);
766
}
767
768
769
770
/* This function is used by the bytecode verifier */
771
772
U_8 *
773
j9bcv_createVerifyErrorString(J9PortLibrary * portLib, J9BytecodeVerificationData * error)
774
{
775
const char *formatString;
776
const char *errorString;
777
U_8 *verifyError;
778
UDATA stringLength = 0;
779
/* Jazz 82615: Statistics data indicates the buffer size of 97% JCK cases is less than 1K */
780
U_8 byteArray[1024];
781
U_8* detailedErrMsg = NULL;
782
UDATA detailedErrMsgLength = 0;
783
784
PORT_ACCESS_FROM_PORT(portLib);
785
786
if ((IDATA) error->errorCode == -1) {
787
/* We were called with an uninitialized buffer, just return a generic error */
788
return NULL;
789
}
790
791
if ((IDATA)error->errorModule == -1) {
792
return NULL;
793
}
794
795
if ((IDATA) error->errorPC == -1) {
796
/* J9NLS_BCV_ERROR_TEMPLATE_NO_PC=%1$s; class=%3$.*2$s, method=%5$.*4$s%7$.*6$s */
797
formatString = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_BCV_ERROR_TEMPLATE_NO_PC, "%s; class=%.*s, method=%.*s%.*s");
798
} else {
799
/* Jazz 82615: Generate the error message framework by default.
800
* The error message framework is not required when the -XX:-VerifyErrorDetails option is specified.
801
*/
802
if (J9_ARE_ALL_BITS_SET(error->verificationFlags, J9_VERIFY_ERROR_DETAILS)
803
&& (0 != error->errorDetailCode)
804
) {
805
/* Jazz 82615: The value of detailedErrMsg may change if the initial byteArray is insufficient to contain the error message framework.
806
* Under such circumstances, it points to the address of newly allocated memory.
807
*/
808
detailedErrMsg = byteArray;
809
detailedErrMsgLength = sizeof(byteArray);
810
/* In the case of failure to allocating memory in building the error message framework,
811
* detailedErrMsg is set to NULL and detailedErrMsgLength is set to 0 on return from getRtvExceptionDetails().
812
* Therefore, it ends up with a simple error message as the buffer for the error message framework has been cleaned up.
813
*/
814
detailedErrMsg = error->javaVM->verboseStruct->getRtvExceptionDetails(error, detailedErrMsg, &detailedErrMsgLength);
815
}
816
817
/*Jazz 82615: fetch the corresponding NLS message when type mismatch error is detected */
818
if (NULL == error->errorSignatureString) {
819
/* J9NLS_BCV_ERROR_TEMPLATE_WITH_PC=%1$s; class=%3$.*2$s, method=%5$.*4$s%7$.*6$s, pc=%8$u */
820
formatString = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_BCV_ERROR_TEMPLATE_WITH_PC, "%s; class=%.*s, method=%.*s%.*s, pc=%u");
821
} else {
822
/*Jazz 82615: J9NLS_BCV_ERROR_TEMPLATE_TYPE_MISMATCH=%1$s; class=%3$.*2$s, method=%5$.*4$s%7$.*6$s, pc=%8$u; Type Mismatch, argument %9$d in signature %11$.*10$s.%13$.*12$s:%15$.*14$s does not match */
823
formatString = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_BCV_ERROR_TEMPLATE_TYPE_MISMATCH,
824
"%s; class=%.*s, method=%.*s%.*s, pc=%u; Type Mismatch, argument %d in signature %.*s.%.*s:%.*s does not match");
825
}
826
}
827
828
/* Determine the size of the error string we need to allocate */
829
errorString = OMRPORT_FROM_J9PORT(PORTLIB)->nls_lookup_message(OMRPORT_FROM_J9PORT(PORTLIB), J9NLS_DO_NOT_APPEND_NEWLINE, (U_32)(error->errorModule), (U_32)(error->errorCode), NULL);
830
stringLength = strlen(errorString);
831
832
stringLength += J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(error->romClass));
833
stringLength += J9UTF8_LENGTH(J9ROMMETHOD_NAME(error->romMethod));
834
stringLength += J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(error->romMethod));
835
stringLength += 10; /* for the PC */
836
if (NULL != error->errorSignatureString) {
837
stringLength += 10; /* for the argument index */
838
stringLength += J9UTF8_LENGTH(error->errorClassString);
839
stringLength += J9UTF8_LENGTH(error->errorMethodString);
840
stringLength += J9UTF8_LENGTH(error->errorSignatureString);
841
}
842
stringLength += strlen(formatString);
843
stringLength += detailedErrMsgLength;
844
845
verifyError = j9mem_allocate_memory(stringLength, J9MEM_CATEGORY_CLASSES);
846
if (NULL != verifyError) {
847
UDATA errStrLength = 0;
848
J9UTF8 * romClassName = J9ROMCLASS_CLASSNAME(error->romClass);
849
J9UTF8 * romMethodName = J9ROMMETHOD_NAME(error->romMethod);
850
J9UTF8 * romMethodSignatureString = J9ROMMETHOD_SIGNATURE(error->romMethod);
851
852
if (NULL == error->errorSignatureString) {
853
errStrLength = j9str_printf(PORTLIB, (char*) verifyError, stringLength, formatString, errorString,
854
(U_32) J9UTF8_LENGTH(romClassName), J9UTF8_DATA(romClassName),
855
(U_32) J9UTF8_LENGTH(romMethodName), J9UTF8_DATA(romMethodName),
856
(U_32) J9UTF8_LENGTH(romMethodSignatureString), J9UTF8_DATA(romMethodSignatureString),
857
error->errorPC);
858
} else {
859
/* Jazz 82615: Print the corresponding NLS message to buffer for type mismatch error */
860
errStrLength = j9str_printf(PORTLIB, (char*) verifyError, stringLength, formatString, errorString,
861
(U_32) J9UTF8_LENGTH(romClassName), J9UTF8_DATA(romClassName),
862
(U_32) J9UTF8_LENGTH(romMethodName), J9UTF8_DATA(romMethodName),
863
(U_32) J9UTF8_LENGTH(romMethodSignatureString), J9UTF8_DATA(romMethodSignatureString),
864
error->errorPC,
865
error->errorArgumentIndex,
866
(U_32) J9UTF8_LENGTH(error->errorClassString), J9UTF8_DATA(error->errorClassString),
867
(U_32) J9UTF8_LENGTH(error->errorMethodString), J9UTF8_DATA(error->errorMethodString),
868
(U_32) J9UTF8_LENGTH(error->errorSignatureString), J9UTF8_DATA(error->errorSignatureString));
869
}
870
871
/* Jazz 82615: Print the error message framework to the existing error buffer */
872
if (detailedErrMsgLength > 0) {
873
j9str_printf(PORTLIB, (char*)&verifyError[errStrLength], stringLength - errStrLength, "%.*s", detailedErrMsgLength, detailedErrMsg);
874
}
875
}
876
877
/* Jazz 82615: Release the memory pointed by detailedErrMsg if allocated with new memory in getRtvExceptionDetails */
878
if (detailedErrMsg != byteArray) {
879
j9mem_free_memory(detailedErrMsg);
880
}
881
882
/* reset the error buffer */
883
RESET_VERIFY_ERROR(error);
884
885
return verifyError;
886
}
887
888
/*
889
* Validates field access compatibility
890
*
891
* returns TRUE if class are compatible
892
* returns FALSE it not compatible
893
* reasonCode (set by isClassCompatibleByName) is:
894
* BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case
895
*/
896
IDATA
897
isFieldAccessCompatible(J9BytecodeVerificationData * verifyData, J9ROMFieldRef * fieldRef, UDATA bytecode, UDATA receiver, IDATA *reasonCode)
898
{
899
J9ROMClass * romClass = verifyData->romClass;
900
J9ROMConstantPoolItem * constantPool = (J9ROMConstantPoolItem *) (romClass + 1);
901
J9UTF8 * utf8string = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[fieldRef->classRefCPIndex]);
902
903
*reasonCode = 0;
904
905
if (bytecode == 181) {/* JBputfield */
906
if ((receiver & BCV_SPECIAL_INIT) == (UDATA) BCV_SPECIAL_INIT) {
907
J9UTF8 *classString = ((J9UTF8 *) J9ROMCLASS_CLASSNAME(romClass));
908
if (utf8string != classString) {
909
/* The following test is not necessary if the class name is uniquely referenced in a class */
910
if (J9UTF8_LENGTH(utf8string) == J9UTF8_LENGTH(classString)) {
911
IDATA i;
912
913
/* Reversed scan typically faster for inequality - most classes share common prefixes */
914
for (i = (IDATA) (J9UTF8_LENGTH(utf8string) - 1); i >= 0; i--) {
915
if (J9UTF8_DATA(utf8string)[i] != J9UTF8_DATA(classString)[i]) {
916
break;
917
}
918
}
919
/* check for comparison success */
920
if (i < 0) {
921
return (IDATA) TRUE;
922
}
923
}
924
return (IDATA) FALSE;
925
} else {
926
return (IDATA) TRUE;
927
}
928
}
929
}
930
return isClassCompatibleByName(verifyData, receiver, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), reasonCode);
931
}
932
933
/* Determine if protected member access is permitted.
934
* currentClass is the current class
935
* declaringClass is the class which defines the member
936
* targetClass is the class for which the member is being used
937
* member: either a J9ROMFieldRef* or a J9ROMNameAndSignature*
938
*
939
* returns TRUE if protected access is permitted,
940
* returns FALSE if protected access is not permitted
941
* reasonCode (set by j9rtv_verifierGetRAMClass) is :
942
* BCV_ERR_INSUFFICIENT_MEMORY if OOM is encountered
943
*/
944
945
UDATA
946
isProtectedAccessPermitted(J9BytecodeVerificationData *verifyData, J9UTF8* declaringClassName, UDATA targetClass, void* member, UDATA isField, IDATA *reasonCode )
947
{
948
J9ROMClass * romClass = verifyData->romClass;
949
950
*reasonCode = 0;
951
952
/* for performance reasons, don't do protection checks unless -Xfuture or -Xverify:doProtectedAccessCheck is specified */
953
if ((0 == (verifyData->vmStruct->javaVM->runtimeFlags & J9RuntimeFlagXfuture))
954
&& (0 == (verifyData->verificationFlags & J9_VERIFY_DO_PROTECTED_ACCESS_CHECK))
955
) {
956
return TRUE;
957
}
958
959
/* Skip protection checks for arrays, they are in the NULL package */
960
if (J9CLASS_ARITY_FROM_CLASS_ENTRY(targetClass) == 0) {
961
J9Class * definingRamClass;
962
J9Class * currentRamClass;
963
J9UTF8 * currentClassName;
964
IDATA rc;
965
966
/* Short circuit if the classes are the same */
967
currentClassName = J9ROMCLASS_CLASSNAME(romClass);
968
if (compareTwoUTF8s(declaringClassName, currentClassName)) {
969
return TRUE;
970
}
971
if (J9ROMCLASS_IS_HIDDEN(romClass)) {
972
/* j9rtv_verifierGetRAMClass won't find hidden classes. We are checking if the current class has access to
973
* proected memeber of declaringClass. We can use the superclass of current class instead here. */
974
currentClassName = J9ROMCLASS_SUPERCLASSNAME(romClass);
975
if (compareTwoUTF8s(declaringClassName, currentClassName)) {
976
return TRUE;
977
}
978
}
979
/* Get the ram classes for the current and defining classes */
980
currentRamClass = j9rtv_verifierGetRAMClass (verifyData, verifyData->classLoader, J9UTF8_DATA(currentClassName), J9UTF8_LENGTH(currentClassName), reasonCode);
981
if ((NULL == currentRamClass) && (BCV_ERR_INSUFFICIENT_MEMORY == *reasonCode)) {
982
return FALSE;
983
}
984
985
/* short circuit - check currentRamClass hierarchy for member - if not found, protected access is permitted */
986
definingRamClass = currentRamClass;
987
if (isField) {
988
rc = findFieldFromRamClass(&definingRamClass, (J9ROMFieldRef *) member, FALSE);
989
} else {
990
rc = findMethodFromRamClass(verifyData, &definingRamClass, (J9ROMNameAndSignature *) member, FALSE);
991
}
992
993
/* Return if member is not found if currentRamClass hierarchy - access okay */
994
if (BCV_NOT_FOUND == rc) return TRUE;
995
996
/* Now chase the definition from the declaringClass */
997
definingRamClass = j9rtv_verifierGetRAMClass (verifyData, verifyData->classLoader, J9UTF8_DATA(declaringClassName), J9UTF8_LENGTH(declaringClassName), reasonCode);
998
if (NULL == definingRamClass) {
999
return FALSE;
1000
}
1001
1002
/* Jazz 106868:
1003
* According to VM Spec at 4.10.1.8 Type Checking for protected Members,
1004
* the protected check applies only to protected members of superclasses of the current class
1005
* protected members in other classes will be caught by the access checking done at resolution.
1006
* So we ignore the protected checking since declaringClass is not the same or super class of currentClass.
1007
*/
1008
if (!isSameOrSuperClassOf (definingRamClass, currentRamClass)) {
1009
return TRUE;
1010
}
1011
1012
if (isField) {
1013
rc = findFieldFromRamClass(&definingRamClass, (J9ROMFieldRef *) member, TRUE);
1014
} else {
1015
rc = findMethodFromRamClass(verifyData, &definingRamClass, (J9ROMNameAndSignature *) member, TRUE);
1016
}
1017
1018
/* Return if the member is not protected or not found */
1019
if ((BCV_SUCCESS == rc) || (BCV_NOT_FOUND == rc)) {
1020
return TRUE;
1021
}
1022
1023
/* Check if in the same package */
1024
if (currentRamClass->packageID == definingRamClass->packageID) return TRUE;
1025
1026
/* Determine if the defining class is the same class or a super class of current class */
1027
if (isSameOrSuperClassOf(definingRamClass, currentRamClass)) {
1028
U_8 * targetClassName = NULL;
1029
UDATA targetClassLength = 0;
1030
J9Class * targetRamClass = NULL;
1031
1032
/* NULL is compatible */
1033
if (targetClass != BCV_BASE_TYPE_NULL) {
1034
/* Get the targetRamClass */
1035
getNameAndLengthFromClassNameList(verifyData, J9CLASS_INDEX_FROM_CLASS_ENTRY(targetClass), &targetClassName, &targetClassLength);
1036
targetRamClass = j9rtv_verifierGetRAMClass(verifyData, verifyData->classLoader, targetClassName, targetClassLength, reasonCode);
1037
if (NULL == targetRamClass) {
1038
return FALSE;
1039
}
1040
1041
/* Determine if the targetRamClass is the same class or a sub class of the current class */
1042
/* flipped logic - currentRamClass is the same class or a super class of the target class */
1043
if (J9ROMCLASS_IS_HIDDEN(romClass)) {
1044
currentClassName = J9ROMCLASS_CLASSNAME(romClass);
1045
if (!J9UTF8_DATA_EQUALS(targetClassName, targetClassLength, J9UTF8_DATA(currentClassName), J9UTF8_LENGTH(currentClassName))) {
1046
/* fail if current class and target class are not the same */
1047
return FALSE;
1048
}
1049
} else {
1050
if (!isSameOrSuperClassOf(currentRamClass, targetRamClass)) {
1051
/* fail */
1052
return FALSE;
1053
}
1054
}
1055
}
1056
}
1057
}
1058
return TRUE;
1059
}
1060
1061
1062
1063
/* return TRUE if identical, FALSE otherwise */
1064
static UDATA compareTwoUTF8s(J9UTF8 * first, J9UTF8 * second)
1065
{
1066
return J9UTF8_EQUALS(first, second);
1067
}
1068
1069
1070
1071
static void getNameAndLengthFromClassNameList (J9BytecodeVerificationData *verifyData, UDATA listIndex, U_8 ** name, UDATA * length)
1072
{
1073
U_32 * offset;
1074
1075
offset = (U_32 *) verifyData->classNameList[listIndex];
1076
*length = (U_32) J9UTF8_LENGTH(offset + 1);
1077
if (offset[0] == 0) {
1078
*name = J9UTF8_DATA(offset + 1);
1079
} else {
1080
J9ROMClass * romClass = verifyData->romClass;
1081
*name = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);
1082
}
1083
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1084
if (IS_QTYPE(*(char *)*name)
1085
&& (';' == *(char *)(*name + (*length - 1)))
1086
) {
1087
/* we are dealing with signature envelope, extract the name from it */
1088
*name += 1;
1089
*length -= 2;
1090
}
1091
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
1092
}
1093
1094
/* return BCV_SUCCESS if field is found
1095
* return BCV_NOT_FOUND if field is not found
1096
* return BCV_FAIL otherwise
1097
*/
1098
1099
static IDATA findFieldFromRamClass (J9Class ** ramClass, J9ROMFieldRef * field, UDATA firstSearch)
1100
{
1101
J9UTF8 * searchName = J9ROMNAMEANDSIGNATURE_NAME(J9ROMFIELDREF_NAMEANDSIGNATURE(field));
1102
1103
for (;;) {
1104
J9ROMFieldShape * currentField;
1105
J9ROMClass * romClass = (*ramClass)->romClass;
1106
J9ROMFieldWalkState state;
1107
1108
/* Walk the instance fields looking for a match */
1109
currentField = romFieldsStartDo(romClass, &state);
1110
while (currentField != NULL) {
1111
if ((currentField->modifiers & J9AccStatic) == 0) {
1112
if (compareTwoUTF8s(searchName, J9ROMFIELDSHAPE_NAME(currentField))) {
1113
if (currentField->modifiers & CFR_ACC_PROTECTED) return BCV_FAIL;
1114
if (firstSearch) return BCV_SUCCESS;
1115
}
1116
}
1117
currentField = romFieldsNextDo(&state);
1118
}
1119
1120
/* Next try the super class */
1121
*ramClass = SUPERCLASS(*ramClass);
1122
if (NULL == *ramClass) return BCV_NOT_FOUND;
1123
}
1124
}
1125
1126
/* return BCV_SUCCESS if method is found
1127
* return BCV_NOT_FOUND if method is not found
1128
* return BCV_FAIL otherwise
1129
*/
1130
static IDATA
1131
findMethodFromRamClass(J9BytecodeVerificationData * verifyData, J9Class ** ramClass, J9ROMNameAndSignature * method, UDATA firstSearch)
1132
{
1133
J9UTF8 * searchName = J9ROMNAMEANDSIGNATURE_NAME(method);
1134
J9UTF8 * searchSignature = J9ROMNAMEANDSIGNATURE_SIGNATURE(method);
1135
1136
for (;;) {
1137
J9ROMClass * romClass = (*ramClass)->romClass;
1138
UDATA redefinedClassIndex = 0;
1139
J9UTF8 * currentClassName = J9ROMCLASS_CLASSNAME(romClass);
1140
J9ROMMethod * currentRomMethod = NULL;
1141
UDATA methodIndex = 0;
1142
1143
/* CMVC 193469: Walk through the redefined classes looking for a class name that
1144
* matches the current class name and use the new class instead */
1145
for (redefinedClassIndex = 0; redefinedClassIndex < verifyData->redefinedClassesCount; redefinedClassIndex++) {
1146
J9ROMClass * currentRedefinedClass = verifyData->redefinedClasses[redefinedClassIndex].replacementClass.romClass;
1147
Assert_RTV_true(NULL != currentRedefinedClass);
1148
1149
if (0 != compareTwoUTF8s(currentClassName, J9ROMCLASS_CLASSNAME(currentRedefinedClass))) {
1150
/* use the redefined class when checking the methods */
1151
romClass = currentRedefinedClass;
1152
break;
1153
}
1154
}
1155
1156
/* Walk the methods looking for a match */
1157
currentRomMethod = J9ROMCLASS_ROMMETHODS(romClass);
1158
for (methodIndex = 0; methodIndex < romClass->romMethodCount; methodIndex++) {
1159
if ((0 != compareTwoUTF8s(searchName, J9ROMMETHOD_NAME(currentRomMethod)))
1160
&& (0 != compareTwoUTF8s(searchSignature, J9ROMMETHOD_SIGNATURE(currentRomMethod)))
1161
) {
1162
if (currentRomMethod->modifiers & CFR_ACC_PROTECTED) return BCV_FAIL;
1163
if (firstSearch) return BCV_SUCCESS;
1164
}
1165
currentRomMethod = J9_NEXT_ROM_METHOD(currentRomMethod);
1166
}
1167
1168
/* Next try the super class */
1169
*ramClass = SUPERCLASS(*ramClass);
1170
if (NULL == *ramClass) return BCV_NOT_FOUND;
1171
}
1172
}
1173
1174
UDATA
1175
parseObjectOrArrayName(J9BytecodeVerificationData *verifyData, U_8 *signature)
1176
{
1177
UDATA arity, arrayType;
1178
U_8 *string = signature;
1179
1180
while (*signature == '[') {
1181
signature++;
1182
}
1183
arity = (UDATA) (signature - string);
1184
if (IS_REF_OR_VAL_SIGNATURE(*signature)) {
1185
U_16 length = 0;
1186
UDATA classIndex = 0;
1187
1188
signature++;
1189
string = signature; /* remember the start of the string */
1190
while (*signature++ != ';') {
1191
length++;
1192
}
1193
arrayType = convertClassNameToStackMapType(verifyData, string, length, 0, arity);
1194
1195
} else {
1196
/* Base arrays have implicit arity of 1 */
1197
arity--;
1198
arrayType = (UDATA) (BCV_TAG_BASE_ARRAY_OR_NULL + (UDATA) baseTypeCharConversion[*signature - 'A']);
1199
}
1200
1201
return arrayType | (arity << BCV_ARITY_SHIFT);
1202
}
1203
1204
1205
void
1206
storeVerifyErrorData (J9BytecodeVerificationData * verifyData, I_16 errorDetailCode, U_32 errorCurrentFramePosition, UDATA errorTargetType, UDATA errorTempData, IDATA currentPC)
1207
{
1208
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
1209
verifyData->errorDetailCode = errorDetailCode;
1210
verifyData->errorCurrentFramePosition = errorCurrentFramePosition;
1211
verifyData->errorTargetType = errorTargetType;
1212
verifyData->errorTempData = errorTempData;
1213
1214
/* Jazz 82615: Set liveStack->pc to the current pc value in the current frame (liveStack)
1215
* info of the detailed error message.
1216
*/
1217
liveStack->pc = (UDATA)currentPC;
1218
}
1219
1220