Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcverify/rtverify.c
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2022 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "bcvcfr.h"
24
#include "j9bcvnls.h"
25
#include "cfrerrnls.h"
26
27
#include "cfreader.h"
28
#include "bcnames.h"
29
#include "pcstack.h"
30
#include "j9protos.h"
31
#include "j9consts.h"
32
#include "omrthread.h"
33
#include "jvminit.h"
34
#include "vrfyconvert.h"
35
#include "bcverify.h"
36
#include "bcverify_internal.h"
37
#include "vrfytbl.h"
38
#include "j9cp.h"
39
40
#include "ut_j9bcverify.h"
41
42
43
static IDATA verifyBytecodes (J9BytecodeVerificationData * verifyData);
44
static IDATA matchStack (J9BytecodeVerificationData * verifyData, J9BranchTargetStack *liveStack, J9BranchTargetStack * targetStack, UDATA inlineMatch);
45
static IDATA findAndMatchStack (J9BytecodeVerificationData *verifyData, IDATA targetPC, IDATA currentPC);
46
static IDATA verifyExceptions (J9BytecodeVerificationData *verifyData);
47
static J9BranchTargetStack * nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *nextStackPC);
48
static IDATA nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA lastPC);
49
static void storeArgumentErrorData (J9BytecodeVerificationData * verifyData, U_32 errorCurrentFramePosition, U_16 errorArgumentIndex);
50
static void storeMethodInfo (J9BytecodeVerificationData * verifyData, J9UTF8* errorClassString, J9UTF8* errorMethodString, J9UTF8* errorSignatureString, IDATA currentPC);
51
52
/*
53
* returns J9Class * on success
54
* returns NULL on error
55
* set reasonCode to BCV_ERR_INSUFFICIENT_MEMORY on OOM
56
*/
57
J9Class *
58
j9rtv_verifierGetRAMClass( J9BytecodeVerificationData *verifyData, J9ClassLoader* classLoader, U_8 *className, UDATA nameLength, IDATA *reasonCode)
59
{
60
J9Class *found = NULL;
61
JavaVM* jniVM = (JavaVM*)verifyData->javaVM;
62
J9ThreadEnv* threadEnv = NULL;
63
J9JavaVM *vm = verifyData->vmStruct->javaVM;
64
(*jniVM)->GetEnv(jniVM, (void**)&threadEnv, J9THREAD_VERSION_1_1);
65
66
#ifdef J9VM_THR_PREEMPTIVE
67
threadEnv->monitor_enter(vm->classTableMutex);
68
#endif
69
70
/* Sniff the class table to see if already loaded */
71
Trc_RTV_j9rtv_verifierGetRAMClass_Entry(verifyData->vmStruct, classLoader, nameLength, className);
72
found = vm->internalVMFunctions->hashClassTableAt (classLoader, className, nameLength);
73
74
#ifdef J9VM_THR_PREEMPTIVE
75
threadEnv->monitor_exit(vm->classTableMutex);
76
#endif
77
78
if (!found) {
79
/* Set reasonCode to BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED if -XX:+ClassRelationshipVerifier is used, the class is not already loaded and if the classfile major version is at least 51 (Java 7) */
80
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_CLASS_RELATIONSHIP_VERIFIER) && (verifyData->romClass->majorVersion >= 51)) {
81
*reasonCode = BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED;
82
return NULL;
83
} else {
84
J9BytecodeVerificationData savedVerifyData;
85
UDATA *currentAlloc;
86
UDATA *internalBufferStart;
87
UDATA *internalBufferEnd;
88
J9VMThread *tmpVMC = verifyData->vmStruct;
89
90
Trc_RTV_j9rtv_verifierGetRAMClass_notFound(verifyData->vmStruct);
91
92
/* Nest class loading */
93
memcpy(&savedVerifyData, verifyData, sizeof(savedVerifyData));
94
verifyData->vmStruct = NULL;
95
96
if (BCV_ERR_INSUFFICIENT_MEMORY == allocateVerifyBuffers (tmpVMC->javaVM->portLibrary, verifyData)) {
97
/* returning BCV_ERR_INSUFFICIENT_MEMORY for OOM condition */
98
Trc_RTV_j9rtv_verifierGetRAMClass_OutOfMemoryException(verifyData->vmStruct, classLoader, nameLength, className);
99
*reasonCode = BCV_ERR_INSUFFICIENT_MEMORY;
100
return NULL;
101
}
102
103
#ifdef J9VM_THR_PREEMPTIVE
104
threadEnv->monitor_exit(verifyData->verifierMutex);
105
#endif
106
107
/* Find the requested class, fully loading it, but not initializing it. */
108
109
found = tmpVMC->javaVM->internalVMFunctions->internalFindClassUTF8(
110
tmpVMC,
111
className,
112
nameLength,
113
classLoader,
114
J9_FINDCLASS_FLAG_THROW_ON_FAIL);
115
116
if (NULL == found) {
117
*reasonCode = BCV_ERR_INACCESSIBLE_CLASS;
118
}
119
120
#ifdef J9VM_THR_PREEMPTIVE
121
/*
122
* Note: if locking both verifierMutex and classTableMutex, they must be entered in that order (CMVC 186043).
123
*/
124
125
threadEnv->monitor_enter(verifyData->verifierMutex);
126
#endif
127
128
freeVerifyBuffers (tmpVMC->javaVM->portLibrary, verifyData);
129
130
/* The currentAlloc, internalBufferStart, internalBufferEnd fields are NOT nested */
131
/* used in bcvalloc/bcvfree - avoid hammering it */
132
/* This should probably be moved out of the struct, but where? - split the struct by scope */
133
currentAlloc = verifyData->currentAlloc;
134
internalBufferStart = verifyData->internalBufferStart;
135
internalBufferEnd = verifyData->internalBufferEnd;
136
137
memcpy(verifyData, &savedVerifyData, sizeof(savedVerifyData));
138
139
verifyData->currentAlloc = currentAlloc;
140
verifyData->internalBufferStart = internalBufferStart;
141
verifyData->internalBufferEnd = internalBufferEnd;
142
}
143
} else {
144
Trc_RTV_j9rtv_verifierGetRAMClass_found(verifyData->vmStruct);
145
}
146
147
Trc_RTV_j9rtv_verifierGetRAMClass_Exit(verifyData->vmStruct);
148
149
return found;
150
}
151
152
153
/*
154
* returns BCV_SUCCESS on success
155
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
156
* returns BCV_ERR_INTERNAL_ERROR on error
157
*/
158
IDATA
159
j9rtv_verifyBytecodes (J9BytecodeVerificationData *verifyData)
160
{
161
J9ROMClass *romClass = verifyData->romClass;
162
J9ROMMethod *romMethod = verifyData->romMethod;
163
164
UDATA oldState = verifyData->vmStruct->omrVMThread->vmState;
165
IDATA result = BCV_SUCCESS;
166
167
verifyData->vmStruct->omrVMThread->vmState = J9VMSTATE_RTVERIFY;
168
169
Trc_RTV_j9rtv_verifyBytecodes_Entry(verifyData->vmStruct,
170
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)),
171
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)));
172
173
if (romMethod->modifiers & CFR_ACC_HAS_EXCEPTION_INFO) {
174
result = verifyExceptions (verifyData);
175
}
176
177
/* Go walk the bytecodes */
178
if (BCV_SUCCESS == result) {
179
result = verifyBytecodes (verifyData);
180
}
181
182
if (BCV_SUCCESS != result) {
183
if (BCV_ERR_INSUFFICIENT_MEMORY == result) {
184
Trc_RTV_j9rtv_verifyBytecodes_OutOfMemoryException(verifyData->vmStruct,
185
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)),
186
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)));
187
188
verifyData->errorModule = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__MODULE;
189
verifyData->errorCode = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
190
} else {
191
verifyData->errorModule = J9NLS_BCV_ERR_NOT_THROWABLE__MODULE;
192
verifyData->errorCode = J9NLS_BCV_ERR_NOT_THROWABLE__ID;
193
}
194
Trc_RTV_j9rtv_verifyBytecodes_VerifyError(verifyData->vmStruct, verifyData->errorCode, verifyData->errorPC);
195
}
196
197
verifyData->vmStruct->omrVMThread->vmState = oldState;
198
Trc_RTV_j9rtv_verifyBytecodes_Exit(verifyData->vmStruct);
199
200
return result;
201
}
202
203
204
/*
205
REMOVED: ( Check for backwards branching and if found, look for uninitialized objects. )
206
Find the target stack and then match.
207
This is only called to match out-of-line stacks - branches and switches.
208
return BCV_SUCCESS on finding matching stack
209
return BCV_FAIL on stack mismatch
210
return BCV_ERR_INSUFFICIENT_MEMORY on OOM
211
*/
212
213
static IDATA
214
findAndMatchStack (J9BytecodeVerificationData *verifyData, IDATA targetPC, IDATA currentPC)
215
{
216
U_32 *bytecodeMap = verifyData->bytecodeMap;
217
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
218
J9BranchTargetStack *targetStack;
219
UDATA stackIndex;
220
IDATA rc = BCV_SUCCESS;
221
222
Trc_RTV_findAndMatchStack_Entry(verifyData->vmStruct, currentPC, targetPC);
223
224
if (bytecodeMap[targetPC] & BRANCH_TARGET) {
225
stackIndex = bytecodeMap[targetPC] >> BRANCH_INDEX_SHIFT;
226
targetStack = BCV_INDEX_STACK (stackIndex);
227
228
/* backwards branch? */
229
if (targetPC < currentPC) {
230
/* Ensure we never backwards branch to code that has an initialized this when this code doesn't.
231
* Remember: the verifier does a *linear* walk of the bytecodes.
232
*/
233
if (TRUE == liveStack->uninitializedThis) {
234
if (TRUE != targetStack->uninitializedThis) {
235
rc = BCV_FAIL;
236
goto exit;
237
}
238
}
239
}
240
241
/* Never considered an inline match if we perform a find */
242
rc = matchStack (verifyData, liveStack, targetStack, FALSE);
243
} else {
244
/* failed to find map */
245
Trc_RTV_findAndMatchStack_StackNotFound(verifyData->vmStruct,
246
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
247
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
248
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
249
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
250
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
251
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
252
targetPC);
253
rc = BCV_FAIL;
254
verifyData->errorDetailCode = BCV_ERR_EXPECT_STACKMAP_FRAME;
255
/* Set the branch target PC value to show up in the error message framework */
256
verifyData->errorTempData = targetPC;
257
}
258
exit:
259
/* Jazz 82615: errorDetailCode has been initialized with 0 (SUCCESS).
260
* liveStack->pc should be updated to the current pc value when any
261
* verification error is detected above.
262
*/
263
if (verifyData->errorDetailCode < 0) {
264
liveStack->pc = (UDATA)currentPC;
265
}
266
Trc_RTV_findAndMatchStack_Exit(verifyData->vmStruct, rc);
267
return rc;
268
}
269
270
271
/*
272
Returns
273
BCV_SUCCESS on success,
274
BCV_FAIL on stack mismatch.
275
BCV_ERR_INSUFFICIENT_MEMORY on OOM.
276
*/
277
static IDATA
278
matchStack(J9BytecodeVerificationData * verifyData, J9BranchTargetStack *liveStack, J9BranchTargetStack * targetStack, UDATA inlineMatch)
279
{
280
UDATA *livePtr = liveStack->stackElements;
281
UDATA *liveTop = RELOAD_STACKTOP(liveStack);
282
UDATA *targetPtr = targetStack->stackElements;
283
UDATA *targetTop = RELOAD_STACKTOP(targetStack);
284
UDATA size = liveStack->stackTopIndex;
285
IDATA rc = BCV_SUCCESS;
286
IDATA reasonCode = 0;
287
288
Trc_RTV_matchStack_Entry(verifyData->vmStruct, inlineMatch);
289
290
if (size != (UDATA) targetStack->stackTopIndex) {
291
Trc_RTV_matchStack_DepthMismatchException(verifyData->vmStruct,
292
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
293
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
294
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
295
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
296
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
297
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
298
size, targetStack->stackTopIndex);
299
rc = BCV_FAIL; /* fail - stack depth mismatch */
300
verifyData->errorDetailCode = BCV_ERR_STACK_SIZE_MISMATCH;
301
/* There are two situations for setting the location of data type on 'stack':
302
* 1) size == 0: it means (U_32)(liveTop - liveStack->stackElements) == 0
303
* and only show up the 1st data type on 'stack'.
304
* 2) size > 0: given the stackTop pointer always points to the next slot
305
* after pushing data type onto 'stack', it needs to step back
306
* by 1 slot to the latest valid data type.
307
*/
308
livePtr = (size > 0) ? (liveTop - 1) : liveTop;
309
goto _errorLocation;
310
}
311
312
/* Note: Target stack frame flag needs to be subset of ours. See JVM sepc 4.10.1.4 */
313
if (liveStack->uninitializedThis && !targetStack->uninitializedThis) {
314
rc = BCV_FAIL;
315
goto _finished;
316
}
317
318
while (livePtr != liveTop) {
319
320
if (*livePtr != *targetPtr) {
321
if ((*targetPtr & BCV_BASE_OR_SPECIAL) == 0) {
322
rc = isClassCompatible (verifyData, *livePtr, *targetPtr, &reasonCode);
323
324
if (FALSE == rc) {
325
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
326
Trc_RTV_matchStack_OutOfMemoryException(verifyData->vmStruct,
327
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
328
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
329
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
330
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
331
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
332
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
333
rc = BCV_ERR_INSUFFICIENT_MEMORY;
334
goto _finished;
335
} else {
336
Trc_RTV_matchStack_IncompatibleClassException(verifyData->vmStruct,
337
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
338
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
339
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
340
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
341
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
342
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
343
(livePtr - liveStack->stackElements), *livePtr, *targetPtr);
344
rc = BCV_FAIL; /* fail - object type mismatch*/
345
goto _incompatibleType;
346
}
347
}
348
} else if (*targetPtr != BCV_BASE_TYPE_TOP) {
349
if ((*targetPtr & BCV_SPECIAL_INIT) && verifyData->createdStackMap) {
350
/* Generated stackmaps can skip the check on the target slot with BCV_SPECIAL_INIT
351
* as this slot is set up based on the bytecode itself rather than decompressed stackmaps.
352
*/
353
} else {
354
Trc_RTV_matchStack_PrimitiveOrSpecialMismatchException(verifyData->vmStruct,
355
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
356
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
357
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
358
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
359
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
360
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
361
(livePtr - liveStack->stackElements), *livePtr, *targetPtr);
362
rc = BCV_FAIL; /* fail - primitive or special mismatch */
363
goto _incompatibleType;
364
}
365
}
366
}
367
livePtr++;
368
targetPtr++;
369
}
370
371
if (inlineMatch) {
372
/* hammer the live stack to be the target stack */
373
Trc_RTV_matchStack_InlineMatchEvent(verifyData->vmStruct);
374
livePtr = liveStack->stackElements;
375
targetPtr = targetStack->stackElements;
376
memcpy (livePtr, targetPtr, size * sizeof(UDATA));
377
378
/* Propagate the uninitialized_this flag to targetStack if liveStack is uninitialized */
379
if (((UDATA)TRUE == liveStack->uninitializedThis) || ((UDATA)TRUE == targetStack->uninitializedThis)) {
380
liveStack->uninitializedThis = targetStack->uninitializedThis = TRUE;
381
}
382
}
383
384
rc = BCV_SUCCESS;
385
386
_finished:
387
Trc_RTV_matchStack_Exit(verifyData->vmStruct, rc);
388
return rc;
389
390
_incompatibleType:
391
/* errorDetailCode has been initialized with 0 (SUCCESS).
392
* Verification error data for incompatible data type should be saved here when any verification error occurs is detected above.
393
*/
394
verifyData->errorDetailCode = BCV_ERR_FRAMES_INCOMPATIBLE_TYPE;
395
verifyData->errorTargetType = *targetPtr;
396
_errorLocation:
397
verifyData->errorCurrentFramePosition = (U_32)(livePtr - liveStack->stackElements);
398
verifyData->errorTargetFrameIndex = (U_32)BCV_STACK_INDEX(targetStack);
399
goto _finished;
400
}
401
402
403
/*
404
Walk the bytecodes linearly and verify that the recorded stack maps match.
405
406
returns BCV_SUCCESS on success
407
returns BCV_ERR_INTERNAL_ERROR on verification error
408
returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
409
*/
410
411
static IDATA
412
verifyBytecodes (J9BytecodeVerificationData * verifyData)
413
{
414
#define CHECK_END \
415
if (pc > length) { \
416
errorType = J9NLS_BCV_ERR_UNEXPECTED_EOF__ID; \
417
verboseErrorCode = BCV_ERR_UNEXPECTED_EOF; \
418
index = (UDATA)-1; \
419
goto _miscError; \
420
}
421
422
J9ROMClass * romClass = verifyData->romClass;
423
J9ROMMethod * romMethod = verifyData->romMethod;
424
J9BranchTargetStack *liveStack;
425
J9BranchTargetStack *currentMapData = NULL;
426
UDATA nextMapIndex = 0;
427
IDATA start = 0;
428
UDATA pc, length, index;
429
J9ROMConstantPoolItem *constantPool;
430
J9ROMConstantPoolItem *info;
431
J9ROMStringRef *classRef;
432
J9UTF8 *utf8string;
433
U_8 *code, *temp, *bcIndex;
434
UDATA returnChar;
435
UDATA bc = 0;
436
UDATA i;
437
UDATA inconsistentStack = FALSE;
438
UDATA inconsistentStack2 = FALSE;
439
UDATA type, type1, type2, arrayType, temp1, temp2, temp3, popCount, receiver, cpIndex;
440
UDATA action = RTV_NOP;
441
UDATA *stackBase, *stackTop, *temps;
442
UDATA *ptr;
443
IDATA target;
444
IDATA i1, i2;
445
U_8 *className;
446
UDATA classIndex, maxStack;
447
UDATA wideIndex = FALSE;
448
IDATA nextStackPC;
449
IDATA nextExceptionStartPC;
450
IDATA rc = 0;
451
U_8 returnBytecode;
452
UDATA errorModule = J9NLS_BCV_ERR_BYTECODES_INVALID__MODULE; /* defaults to BCV NLS catalog */
453
U_16 errorType;
454
I_16 offset16;
455
I_32 offset32;
456
UDATA argCount;
457
UDATA checkIfInsideException = romMethod->modifiers & J9AccMethodHasExceptionInfo;
458
UDATA tempStoreChange;
459
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
460
J9ExceptionHandler *handler;
461
J9UTF8 *catchName;
462
UDATA catchClass;
463
J9SRP *callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(romClass);
464
UDATA* originalStackTop;
465
UDATA originalStackZeroEntry;
466
BOOLEAN isInitMethod;
467
IDATA verboseErrorCode = 0;
468
/* Jazz 82615: Initialized by default if unused */
469
UDATA errorTargetType = (UDATA)-1;
470
UDATA errorStackIndex = (UDATA)-1;
471
UDATA errorTempData = (UDATA)-1;
472
BOOLEAN isNextStack = FALSE;
473
474
Trc_RTV_verifyBytecodes_Entry(verifyData->vmStruct,
475
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
476
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
477
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
478
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
479
480
pc = 0;
481
482
liveStack = (J9BranchTargetStack *) verifyData->liveStack;
483
stackTop = &(liveStack->stackElements[0]);
484
485
/* Determine the initial stack map from the method signature */
486
isInitMethod = liveStack->uninitializedThis = buildStackFromMethodSignature (verifyData, &stackTop, &argCount);
487
488
code = J9_BYTECODE_START_FROM_ROM_METHOD(romMethod);
489
length = (UDATA) J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
490
maxStack = J9_MAX_STACK_FROM_ROM_METHOD(romMethod);
491
492
if (argCount != romMethod->argCount) {
493
errorType = J9NLS_BCV_ERR_ARGUMENTS_INCOMPATIBLE__ID; /* correct error code ??? */
494
/* Jazz 82615: Set the error code and the mismatched argument calculated from the method's signature */
495
verboseErrorCode = BCV_ERR_ARGUMENTS_MISMATCH;
496
errorTempData = argCount;
497
goto _miscError;
498
}
499
500
/* Set the base just past the temps - only args and temps are on the stack after building the signature */
501
/* args and temps are accessed relative to liveStack->stackElements */
502
SAVE_STACKTOP(liveStack, stackTop);
503
liveStack->stackBaseIndex = liveStack->stackTopIndex;
504
505
/* Jazz 105041: Initialize the 1st data slot on 'stack' with 'top' (placeholdler)
506
* to avoid storing garbage data type in the error message buffer
507
* when stack underflow occurs.
508
*/
509
liveStack->stackElements[liveStack->stackBaseIndex] = BCV_BASE_TYPE_TOP;
510
511
RELOAD_LIVESTACK;
512
513
/* result in temp1 is ignored */
514
returnBytecode = getReturnBytecode (romClass, romMethod, &temp1);
515
516
bcIndex = code;
517
518
constantPool = J9_ROM_CP_FROM_ROM_CLASS(romClass);
519
520
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
521
522
/* Determine where the first region of bytecodes covered by an exception handler is */
523
nextExceptionStartPC = nextExceptionStart (verifyData, romMethod, -1);
524
525
/* walk the bytecodes linearly */
526
while (pc < length) {
527
if (inconsistentStack) {
528
_inconsistentStack:
529
/* Jazz 82615: Only used for cases when errorType has not yet been set up for the verification error */
530
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
531
_inconsistentStack2:
532
/* Jazz 82615: Store all verification error data here when the incompatible type issue is detected.
533
* Note: errorTempData is set to -1 by default if unused when verification error occurs.
534
*/
535
storeVerifyErrorData(verifyData, BCV_ERR_INCOMPATIBLE_TYPE, (U_32)errorStackIndex, errorTargetType, errorTempData, start);
536
goto _verifyError;
537
}
538
539
if ((UDATA) (stackTop - stackBase) > maxStack) {
540
errorType = J9NLS_BCV_ERR_STACK_OVERFLOW__ID;
541
/* Jazz 82615: Set the error code and the location of wrong data type on stack (only keep the maximum size for stack) */
542
verboseErrorCode = BCV_ERR_STACK_OVERFLOW;
543
errorStackIndex = stackBase - liveStack->stackElements;
544
if (maxStack > 0) {
545
errorStackIndex += maxStack - 1;
546
}
547
goto _miscError;
548
}
549
550
/* If we are at the point of the next stack map, ensure that the current stack matches the mapped stack */
551
if (pc == (UDATA) nextStackPC) {
552
SAVE_STACKTOP(liveStack, stackTop);
553
rc = matchStack (verifyData, liveStack, currentMapData, TRUE);
554
if (BCV_SUCCESS != rc) {
555
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
556
goto _outOfMemoryError;
557
}
558
/* Jazz 82615: Set liveStack->pc to the next pc value rather than the current pc value (start)
559
* in the case of the matched stack frame in the current frame (liveStack)
560
* of the detailed error message
561
*/
562
liveStack->pc = pc;
563
goto _mapError;
564
}
565
566
/* Matched the expected next stack, find a new next stack */
567
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
568
}
569
570
/* Check the stack against the exception handler stack */
571
if (pc == (UDATA) nextExceptionStartPC) {
572
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
573
SAVE_STACKTOP(liveStack, stackTop);
574
575
/* Save the current liveStack element zero */
576
/* Reset the stack pointer and push the exception on the empty stack */
577
originalStackTop = stackTop;
578
originalStackZeroEntry = liveStack->stackElements[liveStack->stackBaseIndex];
579
580
/* Find all exception handlers from here */
581
for (i = exceptionInfo->catchCount; i; i--, handler++) {
582
if (handler->startPC == pc) {
583
/* Check the maps at the handler PC */
584
/* Modify the liveStack temporarily to contain the handler exception */
585
if (handler->exceptionClassIndex) {
586
catchName = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&constantPool [handler->exceptionClassIndex]));
587
catchClass = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(catchName), J9UTF8_LENGTH(catchName), 0, 0);
588
} else {
589
catchClass = BCV_JAVA_LANG_THROWABLE_INDEX;
590
catchClass <<= BCV_CLASS_INDEX_SHIFT;
591
}
592
593
/* Empty the stack */
594
stackTop = &(liveStack->stackElements[liveStack->stackBaseIndex]);
595
PUSH(catchClass);
596
SAVE_STACKTOP(liveStack, stackTop);
597
598
rc = findAndMatchStack (verifyData, handler->handlerPC, start);
599
if (BCV_SUCCESS != rc) {
600
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
601
goto _outOfMemoryError;
602
}
603
goto _mapError;
604
}
605
}
606
}
607
608
/* Restore liveStack */
609
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
610
stackTop = originalStackTop;
611
612
/* Get next exception start PC of interest */
613
nextExceptionStartPC = nextExceptionStart (verifyData, romMethod, nextExceptionStartPC);
614
}
615
616
bcIndex = code + pc;
617
618
bc = *bcIndex;
619
620
start = pc;
621
pc += (J9JavaInstructionSizeAndBranchActionTable[bc] & 7);
622
CHECK_END;
623
624
if ((stackTop - (JavaStackActionTable[bc] & 7)) < stackBase) {
625
errorType = J9NLS_BCV_ERR_STACK_UNDERFLOW__ID;
626
/* Jazz 82615: Set the error code and the location of data type involved
627
* when the verification error related to stack underflow occurs.
628
*/
629
verboseErrorCode = BCV_ERR_STACK_UNDERFLOW;
630
/* Given that the actual data type involved has not yet been located
631
* through pop operation when stack underflow occurs,
632
* it needs to step back by 1 slot to the actual data type to be manipulated by the opcode.
633
*/
634
errorStackIndex = (stackTop - liveStack->stackElements) - 1;
635
/* Always set to the location of the 1st data type on 'stack' to show up if stackTop <= stackBase
636
* Note: this setup is disabled to avoid decoding the garbage data in the error messages
637
* if the current stack frame is loaded from the next stack (without data on the stack)
638
* of the stackmaps.
639
*/
640
if ((stackTop <= stackBase) && !isNextStack) {
641
errorStackIndex = stackBase - liveStack->stackElements;
642
}
643
goto _miscError;
644
}
645
/* Reset as the flag is only used for the current bytecode */
646
isNextStack = FALSE;
647
648
/* Format: 8bits action, 4bits type Y, 4bits type X */
649
type1 = (UDATA) J9JavaBytecodeVerificationTable[bc];
650
action = type1 >> 8;
651
type2 = (type1 >> 4) & 0xF;
652
type1 = (UDATA) decodeTable[type1 & 0xF];
653
type2 = (UDATA) decodeTable[type2];
654
655
/* Many bytecodes are isomorphic - ie have the same actions on the stack. Walk
656
* based on the action type, rather than the individual bytecode.
657
*/
658
switch (action) {
659
case RTV_NOP:
660
break;
661
662
case RTV_WIDE_LOAD_TEMP_PUSH:
663
wideIndex = TRUE; /* Fall through case !!! */
664
665
case RTV_LOAD_TEMP_PUSH:
666
index = type2 & 0x7;
667
if (type2 == 0) {
668
index = PARAM_8(bcIndex, 1);
669
if (wideIndex) {
670
index = PARAM_16(bcIndex, 1);
671
wideIndex = FALSE;
672
}
673
}
674
if (temps[index] != type1) {
675
if ((type1 != BCV_GENERIC_OBJECT) || (temps[index] & BCV_TAG_BASE_TYPE_OR_TOP)) {
676
inconsistentStack = TRUE;
677
/* Jazz 82615: Set the expected data type and the location of wrong data type
678
* on stack (already in index) when the verification error occurs.
679
*/
680
errorTargetType = type1;
681
errorStackIndex = index;
682
goto _inconsistentStack;
683
}
684
}
685
if (type1 == BCV_GENERIC_OBJECT) {
686
PUSH(temps[index]);
687
break;
688
}
689
if (type1 & BCV_WIDE_TYPE_MASK) {
690
CHECK_TEMP((index + 1), BCV_BASE_TYPE_TOP);
691
if (inconsistentStack) {
692
/* Jazz 82615: Set the expected long/double type (already in type1)
693
* and the location of wrong data type on stack when the verification error occurs.
694
*/
695
errorTargetType = BCV_BASE_TYPE_TOP;
696
/* Save the long/double type to errorTempData (verifyData->errorTempData)
697
* so as to ensure the wrong data type is the 2nd slot of long/double type
698
* in the error message framework rather than a 'top' type.
699
*/
700
errorTempData = type1;
701
errorStackIndex = index + 1;
702
goto _inconsistentStack;
703
}
704
} /* Fall through case !!! */
705
706
case RTV_PUSH_CONSTANT:
707
708
_pushConstant:
709
PUSH(type1);
710
if (type1 & BCV_WIDE_TYPE_MASK) {
711
PUSH(BCV_BASE_TYPE_TOP);
712
}
713
break;
714
715
case RTV_PUSH_CONSTANT_POOL_ITEM:
716
switch (bc) {
717
case JBldc:
718
case JBldcw:
719
if (bc == JBldc) {
720
index = PARAM_8(bcIndex, 1);
721
} else {
722
index = PARAM_16(bcIndex, 1);
723
}
724
stackTop = pushLdcType(verifyData, romClass, index, stackTop);
725
break;
726
727
/* Change lookup table to generate constant of correct type */
728
case JBldc2lw:
729
PUSH_LONG_CONSTANT;
730
break;
731
732
case JBldc2dw:
733
PUSH_DOUBLE_CONSTANT;
734
break;
735
}
736
break;
737
738
case RTV_ARRAY_FETCH_PUSH:
739
POP_TOS_INTEGER;
740
if (inconsistentStack) {
741
/* Jazz 82615: Set the expected data type and the location of wrong data type
742
* on stack when the verification error occurs.
743
*/
744
errorTargetType = BCV_BASE_TYPE_INT;
745
errorStackIndex = stackTop - liveStack->stackElements;
746
goto _inconsistentStack;
747
}
748
arrayType = POP;
749
if (arrayType != BCV_BASE_TYPE_NULL) {
750
if (bc == JBaaload) {
751
inconsistentStack |= arrayType & BCV_BASE_OR_SPECIAL;
752
inconsistentStack |= (arrayType & BCV_ARITY_MASK) == 0;
753
if (inconsistentStack) {
754
/* Jazz 82615: Set the expected data type (presumably object array with 1 dimension)
755
* and the location of wrong data type on stack when the verification error occurs.
756
*/
757
errorTargetType = (UDATA)(BCV_GENERIC_OBJECT | (1 << BCV_ARITY_SHIFT));
758
errorStackIndex = stackTop - liveStack->stackElements;
759
goto _inconsistentStack;
760
}
761
type1 = arrayType - 0x01000000; /* reduce types arity by one */
762
PUSH(type1);
763
break;
764
} else {
765
type = (UDATA) J9JavaBytecodeArrayTypeTable[bc - JBiaload];
766
/* The operand checking for baload needs to cover the case of boolean arrays */
767
CHECK_BOOL_ARRAY(JBbaload, bc, type);
768
if (inconsistentStack) {
769
/* Jazz 82615: Set the expected data type (already in type) and the location of wrong data type
770
* on stack when the verification error occurs.
771
*/
772
errorTargetType = type;
773
errorStackIndex = stackTop - liveStack->stackElements;
774
goto _inconsistentStack;
775
}
776
}
777
}
778
goto _pushConstant;
779
break;
780
781
case RTV_WIDE_POP_STORE_TEMP:
782
wideIndex = TRUE; /* Fall through case !!! */
783
784
case RTV_POP_STORE_TEMP:
785
index = type2 & 0x7;
786
if (type2 == 0) {
787
index = PARAM_8(bcIndex, 1);
788
if (wideIndex) {
789
index = PARAM_16(bcIndex, 1);
790
wideIndex = FALSE;
791
}
792
}
793
POP_TOS_TYPE( type, type1 );
794
if (inconsistentStack) {
795
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
796
* the location of wrong data type on stack when the verification error occurs.
797
*/
798
errorTargetType = BCV_BASE_TYPE_TOP;
799
/* Save the long/double type to errorTempData (verifyData->errorTempData)
800
* so as to ensure the wrong data type is the 2nd slot of long/double type
801
* in the error message framework rather than a 'top' type.
802
*/
803
errorTempData = type1;
804
/* The location of wrong data type needs to adjusted back to the right place
805
* because it pops twice from the stack for the wide type.
806
*/
807
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
808
goto _inconsistentStack;
809
}
810
811
tempStoreChange = FALSE;
812
813
if (type != type1) {
814
if ((type1 != BCV_GENERIC_OBJECT) || (type & BCV_TAG_BASE_TYPE_OR_TOP)) {
815
inconsistentStack = TRUE;
816
/* Jazz 82615: Set the expected data type and the location of wrong data type
817
* on stack when the verification error occurs.
818
*/
819
errorTargetType = type1;
820
errorStackIndex = stackTop - liveStack->stackElements;
821
goto _inconsistentStack;
822
}
823
}
824
825
/* because of pre-index local clearing - the order here matters */
826
if (type1 & BCV_WIDE_TYPE_MASK) {
827
tempStoreChange = (temps[index + 1] != BCV_BASE_TYPE_TOP);
828
STORE_TEMP((index + 1), BCV_BASE_TYPE_TOP);
829
}
830
tempStoreChange |= (type != temps[index]);
831
STORE_TEMP(index, type);
832
833
if (checkIfInsideException && tempStoreChange) {
834
/* If we've stored a value into an arg/local, and it's of a different type than was
835
* originally there, we need to ensure that we are still compatible with all our
836
* exception handlers.
837
*
838
* For all exception handlers covering this instruction
839
*/
840
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
841
SAVE_STACKTOP(liveStack, stackTop);
842
843
/* Save the current liveStack element zero */
844
/* Reset the stack pointer to push the exception on the empty stack */
845
originalStackTop = stackTop;
846
originalStackZeroEntry = liveStack->stackElements[liveStack->stackBaseIndex];
847
848
/* Find all exception handlers from here */
849
for (i = exceptionInfo->catchCount; i; i--, handler++) {
850
if (((UDATA) start >= handler->startPC) && ((UDATA) start < handler->endPC)) {
851
#ifdef DEBUG_BCV
852
printf("exception map change check at startPC: %d\n", handler->startPC);
853
#endif
854
/* Check the maps at the handler PC */
855
/* Modify the liveStack temporarily to contain the handler exception */
856
if (handler->exceptionClassIndex) {
857
catchName = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&constantPool [handler->exceptionClassIndex]));
858
catchClass = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(catchName), J9UTF8_LENGTH(catchName), 0, 0);
859
} else {
860
catchClass = BCV_JAVA_LANG_THROWABLE_INDEX;
861
catchClass <<= BCV_CLASS_INDEX_SHIFT;
862
}
863
864
stackTop = &(liveStack->stackElements[liveStack->stackBaseIndex]);
865
PUSH(catchClass);
866
SAVE_STACKTOP(liveStack, stackTop);
867
868
rc = findAndMatchStack (verifyData, handler->handlerPC, start);
869
if (BCV_SUCCESS != rc) {
870
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
871
goto _outOfMemoryError;
872
}
873
goto _mapError;
874
}
875
}
876
}
877
878
/* Restore liveStack */
879
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
880
stackTop = originalStackTop;
881
}
882
break;
883
884
case RTV_ARRAY_STORE:
885
POP_TOS_TYPE( type, type1 );
886
if (inconsistentStack) {
887
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
888
* the location of wrong data type on stack when the verification error occurs.
889
*/
890
errorTargetType = BCV_BASE_TYPE_TOP;
891
/* Save the long/double type to errorTempData (verifyData->errorTempData)
892
* so as to ensure the wrong data type is the 2nd slot of long/double type
893
* in the error message framework rather than a 'top' type.
894
*/
895
errorTempData = type1;
896
/* The location of wrong data type needs to adjusted back to the right place
897
* because it pops twice from the stack for the wide type.
898
*/
899
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
900
goto _inconsistentStack;
901
}
902
POP_TOS_INTEGER;
903
if (inconsistentStack) {
904
/* Jazz 82615: Set the expected data type and the location of wrong data type
905
* on stack when the verification error occurs.
906
*/
907
errorTargetType = BCV_BASE_TYPE_INT;
908
errorStackIndex = stackTop - liveStack->stackElements;
909
goto _inconsistentStack;
910
}
911
arrayType = POP;
912
if (arrayType != BCV_BASE_TYPE_NULL) {
913
if (bc == JBaastore) {
914
inconsistentStack |= (arrayType | type) & BCV_BASE_OR_SPECIAL;
915
if (inconsistentStack) {
916
/* Jazz 82615: Set the expected data type and the location of wrong data type on stack when the verification error occurs.
917
* Note: Given that the current location on stack is for arrayType, it needs to move forward by two slots
918
* to skip over the arrayType plus the index of array so as to reach the location of wrong type (value stored in the array).
919
*/
920
errorTargetType = type1;
921
errorStackIndex = (stackTop - liveStack->stackElements) + 2;
922
goto _inconsistentStack;
923
}
924
inconsistentStack |= (arrayType & BCV_ARITY_MASK) == 0;
925
if (inconsistentStack) {
926
/* Jazz 82615: Set the expected data type (array of object reference)
927
* and the location of wrong data type on stack when the verification error occurs.
928
*/
929
errorTargetType = type1 | (1 << BCV_ARITY_SHIFT);
930
errorStackIndex = stackTop - liveStack->stackElements;
931
goto _inconsistentStack;
932
}
933
} else {
934
inconsistentStack |= (type != type1);
935
if (inconsistentStack) {
936
/* Jazz 82615: Set the expected data type and the location of wrong data type on stack when the verification error occurs.
937
* Note: Given that the current location on stack is for arrayType, it needs to move forward by two slots
938
* to skip over the index of array and get to the location of wrong type (value stored in the array).
939
*/
940
errorTargetType = type1;
941
errorStackIndex = (stackTop - liveStack->stackElements) + 2;
942
goto _inconsistentStack;
943
}
944
945
type2 = (UDATA) J9JavaBytecodeArrayTypeTable[bc - JBiastore];
946
/* The operand checking for bastore needs to cover the case of boolean arrays */
947
CHECK_BOOL_ARRAY(JBbastore, bc, type2);
948
if (inconsistentStack) {
949
/* Jazz 82615: Set the expected data type and the location of wrong data type
950
* on stack when the verification error occurs.
951
*/
952
errorTargetType = type2;
953
errorStackIndex = stackTop - liveStack->stackElements;
954
goto _inconsistentStack;
955
}
956
}
957
}
958
break;
959
960
case RTV_INCREMENT:
961
index = PARAM_8(bcIndex, 1);
962
if (bc == JBiincw) {
963
index = PARAM_16(bcIndex, 1);
964
}
965
CHECK_TEMP_INTEGER(index);
966
if (inconsistentStack) {
967
/* Jazz 82615: Set the expected data type and the location of wrong data type on stack
968
* (already in index) when the verification error occurs.
969
*/
970
errorTargetType = BCV_BASE_TYPE_INT;
971
errorStackIndex = index;
972
goto _inconsistentStack;
973
}
974
break;
975
976
case RTV_POP_2_PUSH:
977
POP_TOS_TYPE_EQUAL( type, type1 );
978
if (inconsistentStack) {
979
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
980
* the location of wrong data type on stack when the verification error occurs.
981
*/
982
errorTargetType = BCV_BASE_TYPE_TOP;
983
/* Save the long/double type to errorTempData (verifyData->errorTempData)
984
* so as to ensure the wrong data type is the 2nd slot of long/double type
985
* in the error message framework rather than a 'top' type.
986
*/
987
errorTempData = type1;
988
/* The location of wrong data type needs to adjusted back to the right place
989
* because it pops twice from the stack for the wide type.
990
*/
991
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
992
goto _inconsistentStack;
993
/* Jazz 82615: the second inconsistent stack case in POP_TOS_TYPE_EQUAL should be addressed here */
994
} else if (inconsistentStack2) {
995
errorTargetType = type1;
996
errorStackIndex = stackTop - liveStack->stackElements;
997
goto _inconsistentStack;
998
}
999
POP_TOS_TYPE_EQUAL( type, type1 );
1000
if (inconsistentStack) {
1001
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
1002
* the location of wrong data type on stack when the verification error occurs.
1003
*/
1004
errorTargetType = BCV_BASE_TYPE_TOP;
1005
/* Save the long/double type to errorTempData (verifyData->errorTempData)
1006
* so as to ensure the wrong data type is the 2nd slot of long/double type
1007
* in the error message framework rather than a 'top' type.
1008
*/
1009
errorTempData = type1;
1010
/* The location of wrong data type needs to adjusted back to the right place
1011
* because it pops twice from the stack for the wide type.
1012
*/
1013
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
1014
goto _inconsistentStack;
1015
/* Jazz 82615: the second inconsistent stack case in POP_TOS_TYPE_EQUAL should be addressed here */
1016
} else if (inconsistentStack2) {
1017
errorTargetType = type1;
1018
errorStackIndex = stackTop - liveStack->stackElements;
1019
goto _inconsistentStack;
1020
}
1021
goto _pushConstant;
1022
break;
1023
1024
case RTV_POP_X_PUSH_X:
1025
/* Shifts only have non-zero type2 */
1026
if (type2) {
1027
POP_TOS_INTEGER;
1028
if (inconsistentStack) {
1029
/* Jazz 82615: Set the expected data type and the location of wrong data type
1030
* on stack when the verification error occurs.
1031
*/
1032
errorTargetType = BCV_BASE_TYPE_INT;
1033
errorStackIndex = stackTop - liveStack->stackElements;
1034
goto _inconsistentStack;
1035
}
1036
}
1037
POP_TOS_TYPE_EQUAL( type, type1 );
1038
if (inconsistentStack) {
1039
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
1040
* the location of wrong data type on stack when the verification error occurs.
1041
*/
1042
errorTargetType = BCV_BASE_TYPE_TOP;
1043
/* Save the long/double type to errorTempData (verifyData->errorTempData)
1044
* so as to ensure the wrong data type is the 2nd slot of long/double type
1045
* in the error message framework rather than a 'top' type.
1046
*/
1047
errorTempData = type1;
1048
/* The location of wrong data type needs to adjusted back to the right place
1049
* because it pops twice from the stack for the wide type.
1050
*/
1051
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
1052
goto _inconsistentStack;
1053
/* Jazz 82615: the second inconsistent stack case in POP_TOS_TYPE_EQUAL should be addressed here */
1054
} else if (inconsistentStack2) {
1055
errorTargetType = type1;
1056
errorStackIndex = stackTop - liveStack->stackElements;
1057
goto _inconsistentStack;
1058
}
1059
goto _pushConstant;
1060
break;
1061
1062
case RTV_POP_X_PUSH_Y:
1063
POP_TOS_TYPE_EQUAL( type, type1 );
1064
if (inconsistentStack) {
1065
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
1066
* the location of wrong data type on stack when the verification error occurs.
1067
*/
1068
errorTargetType = BCV_BASE_TYPE_TOP;
1069
/* Save the long/double type to errorTempData (verifyData->errorTempData)
1070
* so as to ensure the wrong data type is the 2nd slot of long/double type
1071
* in the error message framework rather than a 'top' type.
1072
*/
1073
errorTempData = type1;
1074
/* The location of wrong data type needs to adjusted back to the right place
1075
* because it pops twice from the stack for the wide type.
1076
*/
1077
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
1078
goto _inconsistentStack;
1079
/* Jazz 82615: the second inconsistent stack case in POP_TOS_TYPE_EQUAL should be addressed here */
1080
} else if (inconsistentStack2) {
1081
errorTargetType = type1;
1082
errorStackIndex = stackTop - liveStack->stackElements;
1083
goto _inconsistentStack;
1084
}
1085
type1 = type2;
1086
goto _pushConstant;
1087
break;
1088
1089
case RTV_BRANCH:
1090
popCount = type2 - 8;
1091
for (i = 0; i < popCount; i++) {
1092
if (type1 == BCV_GENERIC_OBJECT) {
1093
type = POP;
1094
/* Jazz 89060: According to the explanation of the Verification type hierarchy/rules
1095
* at section 4.10.1.2 Verification Type System (The JVM Specification Java SE 8 Edition):
1096
* isAssignable(uninitialized, X) :- isAssignable(reference, X).
1097
* isAssignable(uninitializedThis, X) :- isAssignable(uninitialized, X).
1098
* isAssignable(uninitialized(_), X) :- isAssignable(uninitialized, X).
1099
*
1100
* It means that 'uninitializedThis' is a subtype of 'reference',
1101
* and then 'uninitializedThis' is compatible with BCV_GENERIC_OBJECT ( 'reference' type )
1102
*/
1103
if (J9_ARE_NO_BITS_SET(type, BCV_SPECIAL)) {
1104
IDATA reasonCode = 0;
1105
rc = isClassCompatible (verifyData, type, BCV_GENERIC_OBJECT, &reasonCode);
1106
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1107
goto _outOfMemoryError;
1108
}
1109
1110
inconsistentStack |= (FALSE == rc);
1111
if (inconsistentStack) {
1112
/* Jazz 82615: Set the expected data type and the location of wrong data type
1113
* on stack when the verification error occurs.
1114
*/
1115
errorTargetType = BCV_GENERIC_OBJECT;
1116
errorStackIndex = stackTop - liveStack->stackElements;
1117
goto _inconsistentStack;
1118
}
1119
}
1120
} else {
1121
POP_TOS_INTEGER;
1122
if (inconsistentStack) {
1123
/* Jazz 82615: Set the expected data type and the location of wrong data type
1124
* on stack when the verification error occurs.
1125
*/
1126
errorTargetType = BCV_BASE_TYPE_INT;
1127
errorStackIndex = stackTop - liveStack->stackElements;
1128
goto _inconsistentStack;
1129
}
1130
}
1131
}
1132
1133
if (bc == JBgotow) {
1134
offset32 = (I_32) PARAM_32(bcIndex, 1);
1135
target = start + offset32;
1136
} else {
1137
offset16 = (I_16) PARAM_16(bcIndex, 1);
1138
target = start + offset16;
1139
}
1140
1141
SAVE_STACKTOP(liveStack, stackTop);
1142
/* Merge our stack to the target */
1143
rc = findAndMatchStack (verifyData, target, start);
1144
if (BCV_SUCCESS != rc) {
1145
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
1146
goto _outOfMemoryError;
1147
}
1148
goto _mapError;
1149
}
1150
1151
/* Unconditional branch */
1152
if (popCount == 0) {
1153
goto _newStack;
1154
}
1155
break;
1156
1157
case RTV_RETURN:
1158
utf8string = J9ROMMETHOD_SIGNATURE(romMethod);
1159
temp = &J9UTF8_DATA(utf8string)[J9UTF8_LENGTH(utf8string) - 2];
1160
returnChar = (UDATA) temp[1];
1161
if (temp[0] != ')') {
1162
returnChar = 0;
1163
className = J9UTF8_DATA(utf8string);
1164
while (*className++ != ')');
1165
temp1 = parseObjectOrArrayName(verifyData, className);
1166
}
1167
1168
switch (bc) {
1169
1170
case JBreturn0:
1171
case JBsyncReturn0:
1172
case JBreturnFromConstructor:
1173
inconsistentStack |= (returnChar != 'V');
1174
if (inconsistentStack) {
1175
_illegalPrimitiveReturn:
1176
/* Jazz 82615: Set the error code in the case of verification error on return. */
1177
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
1178
verboseErrorCode = BCV_ERR_WRONG_RETURN_TYPE;
1179
goto _miscError;
1180
}
1181
break;
1182
1183
case JBreturn1:
1184
case JBreturnB:
1185
case JBreturnC:
1186
case JBreturnS:
1187
case JBreturnZ:
1188
case JBsyncReturn1:
1189
/* Note: for synchronized return{B,C,S,Z}, JBgenericReturn is used */
1190
if (returnChar) {
1191
U_32 returnType = 0;
1192
/* single character return description */
1193
if ((returnChar < 'A') || (returnChar > 'Z')) {
1194
inconsistentStack = TRUE;
1195
goto _illegalPrimitiveReturn;
1196
}
1197
type = (UDATA) oneArgTypeCharConversion[returnChar - 'A'];
1198
POP_TOS(type);
1199
1200
/* check methods that return char, byte, short, or bool use the right opcode */
1201
if (BCV_BASE_TYPE_INT == type){
1202
switch(bc) {
1203
case JBreturnB:
1204
returnType = BCV_BASE_TYPE_BYTE_BIT;
1205
break;
1206
1207
case JBreturnC:
1208
returnType = BCV_BASE_TYPE_CHAR_BIT;
1209
break;
1210
1211
case JBreturnS:
1212
returnType = BCV_BASE_TYPE_SHORT_BIT;
1213
break;
1214
1215
case JBreturnZ:
1216
returnType = BCV_BASE_TYPE_BOOL_BIT;
1217
break;
1218
/* Note: synchronized return of b,c,s,z are handled as a JBgenericReturn */
1219
case JBreturn1:
1220
case JBsyncReturn1:
1221
returnType = BCV_BASE_TYPE_INT_BIT;
1222
break;
1223
default:
1224
Trc_RTV_j9rtv_verifyBytecodes_Unreachable(verifyData->vmStruct,
1225
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1226
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1227
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
1228
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
1229
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1230
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1231
__LINE__);
1232
break;
1233
}
1234
inconsistentStack |= returnType != baseTypeCharConversion[returnChar - 'A'];
1235
}
1236
if (inconsistentStack) {
1237
/* Jazz 82615: Set the expected data type (already in type) and
1238
* the location of wrong data type on stack when the verification error occurs.
1239
*/
1240
errorTargetType = type;
1241
errorStackIndex = stackTop - liveStack->stackElements;
1242
goto _inconsistentStack;
1243
}
1244
1245
} else {
1246
IDATA reasonCode = 0;
1247
1248
/* Object */
1249
POP_TOS_OBJECT(type);
1250
if (inconsistentStack) {
1251
/* Jazz 82615: Set the expected data type and the location of wrong data type on stack when the verification error occurs. */
1252
errorTargetType = BCV_GENERIC_OBJECT;
1253
errorStackIndex = stackTop - liveStack->stackElements;
1254
goto _inconsistentStack;
1255
}
1256
1257
rc = isClassCompatible(verifyData, type, temp1, &reasonCode);
1258
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1259
goto _outOfMemoryError;
1260
}
1261
inconsistentStack |= (FALSE == rc);
1262
if (inconsistentStack) {
1263
/* Jazz 82615: Set the expected data type and the location of wrong data type
1264
* on stack when the verification error occurs.
1265
*/
1266
errorTargetType = temp1;
1267
errorStackIndex = stackTop - liveStack->stackElements;
1268
goto _inconsistentStack;
1269
}
1270
}
1271
break;
1272
1273
case JBreturn2:
1274
case JBsyncReturn2:
1275
/* single character return description */
1276
if ((returnChar < 'A') || (returnChar > 'Z')) {
1277
inconsistentStack = TRUE;
1278
goto _illegalPrimitiveReturn;
1279
}
1280
type = (UDATA) argTypeCharConversion[returnChar - 'A'];
1281
POP_TOS_2(type);
1282
if (inconsistentStack) {
1283
/* Jazz 82615: Set the expected data type (already in type)
1284
* and the location of wrong data type on stack when the verification error occurs.
1285
*/
1286
errorTargetType = type;
1287
errorStackIndex = stackTop - liveStack->stackElements;
1288
goto _inconsistentStack;
1289
}
1290
break;
1291
1292
case JBgenericReturn:
1293
/* Decide based on the signature of this method what the return is supposed to be */
1294
if (returnChar) {
1295
/* single character return description */
1296
if ((returnChar < 'A') || (returnChar > 'Z')) {
1297
inconsistentStack = TRUE;
1298
goto _illegalPrimitiveReturn;
1299
}
1300
if (returnChar != 'V') {
1301
type = (UDATA) argTypeCharConversion[returnChar - 'A'];
1302
if ((returnChar == 'J') || (returnChar == 'D')) {
1303
POP_TOS(BCV_BASE_TYPE_TOP);
1304
if (inconsistentStack) {
1305
/* Jazz 82615: Set the expected long/double type and the location of wrong data type on stack when the verification error occurs. */
1306
errorTempData = ('J' == returnChar) ? BCV_BASE_TYPE_LONG : BCV_BASE_TYPE_DOUBLE;
1307
errorTargetType = BCV_BASE_TYPE_TOP;
1308
errorStackIndex = stackTop - liveStack->stackElements;
1309
goto _inconsistentStack;
1310
}
1311
}
1312
POP_TOS(type);
1313
if (inconsistentStack) {
1314
/* Jazz 82615: Set the expected data type (already in type) and
1315
* the location of wrong data type on stack when the verification error occurs.
1316
*/
1317
errorTargetType = type;
1318
errorStackIndex = stackTop - liveStack->stackElements;
1319
goto _inconsistentStack;
1320
}
1321
}
1322
} else {
1323
IDATA reasonCode = 0;
1324
1325
/* Object */
1326
POP_TOS_OBJECT(type);
1327
if (inconsistentStack) {
1328
/* Jazz 82615: Set the expected data type and the location of wrong data type
1329
* on stack when the verification error occurs.
1330
*/
1331
errorTargetType = BCV_GENERIC_OBJECT;
1332
errorStackIndex = stackTop - liveStack->stackElements;
1333
goto _inconsistentStack;
1334
}
1335
1336
rc = isClassCompatible(verifyData, type, temp1, &reasonCode);
1337
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1338
goto _outOfMemoryError;
1339
}
1340
inconsistentStack |= (FALSE == rc);
1341
if (inconsistentStack) {
1342
/* Jazz 82615: Set the expected data type and the location of wrong data type
1343
* on stack when the verification error occurs.
1344
*/
1345
errorTargetType = temp1;
1346
errorStackIndex = stackTop - liveStack->stackElements;
1347
goto _inconsistentStack;
1348
}
1349
}
1350
1351
/* Don't rewrite the return bytecode for j.l.Object.<init>()V or if the romClass is in the shared classes cache*/
1352
if ((stackTop == stackBase)
1353
&& ((argCount != 1) || (returnBytecode != JBreturnFromConstructor) || (J9ROMCLASS_SUPERCLASSNAME(romClass) != NULL))
1354
&& (FALSE == verifyData->romClassInSharedClasses)
1355
) {
1356
/* Rewrite clean return if empty stack - needed for StackMap/StackMapTable attribute methods */
1357
*bcIndex = returnBytecode;
1358
}
1359
1360
break;
1361
}
1362
1363
/* If this is <init>, need to ensure that the uninitialized_this
1364
* has been initialized. Can be determined from the stack map's
1365
* flag
1366
*/
1367
if (isInitMethod) {
1368
if (liveStack->uninitializedThis == (UDATA)TRUE){
1369
errorType = J9NLS_BCV_ERR_INIT_NOT_CALL_INIT__ID;
1370
/* Jazz 82615: Set the error code and the location of data type on stack in the case of the verification error unrelated to incompatible type.*/
1371
verboseErrorCode = BCV_ERR_INIT_NOT_CALL_INIT;
1372
/* Given that there is no real wrong data type on stack in such case, the stackTop pointer needs to step back by one slot
1373
* to point to the current data type on stack so as to print all data types correctly in the error message framework.
1374
*/
1375
errorStackIndex = (stackTop - liveStack->stackElements) - 1;
1376
/* Always set to the location of the 1st data type on 'stack' to show up if stackTop <= stackBase */
1377
if (stackTop <= stackBase) {
1378
errorStackIndex = stackBase - liveStack->stackElements;
1379
}
1380
goto _miscError;
1381
}
1382
}
1383
1384
goto _newStack;
1385
break;
1386
1387
case RTV_STATIC_FIELD_ACCESS:
1388
{
1389
IDATA reasonCode = 0;
1390
/* Jazz 82615: Save the location of wrong data type (receiver) */
1391
UDATA *receiverPtr = NULL;
1392
1393
index = PARAM_16(bcIndex, 1);
1394
info = &constantPool[index];
1395
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMFIELDREF_NAMEANDSIGNATURE((J9ROMFieldRef *) info))));
1396
1397
receiver = BCV_BASE_TYPE_NULL; /* makes class compare work with statics */
1398
1399
if ((bc & 1)
1400
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1401
|| (bc == JBwithfield)
1402
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1403
) {
1404
/* case for JBwithfield and odd bc's which are JBputfield/JBpustatic */
1405
type = POP;
1406
if ((*J9UTF8_DATA(utf8string) == 'D') || (*J9UTF8_DATA(utf8string) == 'J')) {
1407
inconsistentStack |= (type != BCV_BASE_TYPE_TOP);
1408
if (inconsistentStack) {
1409
/* Jazz 82615: Set the expected long/double type and the location of wrong data type
1410
* on stack when the verification error occurs.
1411
*/
1412
errorTempData = ('J' == *J9UTF8_DATA(utf8string)) ? BCV_BASE_TYPE_LONG : BCV_BASE_TYPE_DOUBLE;
1413
errorTargetType = BCV_BASE_TYPE_TOP;
1414
errorStackIndex = stackTop - liveStack->stackElements;
1415
goto _inconsistentStack;
1416
}
1417
type = POP;
1418
}
1419
/* HACK: Pushes the return type without moving the stack pointer */
1420
pushFieldType(verifyData, utf8string, stackTop);
1421
if (*stackTop & BCV_TAG_BASE_TYPE_OR_TOP) {
1422
inconsistentStack |= (*stackTop != type);
1423
} else {
1424
rc = isClassCompatible(verifyData, type, *stackTop, &reasonCode);
1425
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1426
goto _outOfMemoryError;
1427
}
1428
1429
inconsistentStack |= (FALSE == rc);
1430
}
1431
if (inconsistentStack) {
1432
/* Jazz 82615: Set the expected data type and the location of wrong data type on stack when the verification error occurs. */
1433
errorTargetType = *stackTop;
1434
errorStackIndex = stackTop - liveStack->stackElements;
1435
1436
/* Jazz 82615: This is an exception when storing the verification error data, which was originally caused by the hack (pushFieldType) above.
1437
* The stackTop pointer doesn't get updated after calling pushFieldType() to store the return type, so *stackTop stores
1438
* the expected data type rather than the wrong data type which has already been popped up from stack.
1439
*
1440
* According to the output format of error message framework, only the wrong data type is expected to occur at *stackTop on stack
1441
* rather than the expected data type. Thus, the wrong data type must be pushed back to *stackTop after saving the expected data type
1442
* somewhere else.
1443
*/
1444
PUSH(type);
1445
goto _inconsistentStack;
1446
}
1447
1448
if (bc == JBputfield) {
1449
receiver = POP;
1450
/* Jazz 82615: Save the location of receiver */
1451
receiverPtr = stackTop;
1452
}
1453
} else {
1454
/* JBgetfield/JBgetstatic - even bc's */
1455
if (bc == JBgetfield) {
1456
receiver = POP;
1457
/* Jazz 82615: Save the location of receiver */
1458
receiverPtr = stackTop;
1459
}
1460
stackTop = pushFieldType(verifyData, utf8string, stackTop);
1461
}
1462
1463
rc = isFieldAccessCompatible (verifyData, (J9ROMFieldRef *) info, bc, receiver, &reasonCode);
1464
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1465
goto _outOfMemoryError;
1466
}
1467
inconsistentStack |= (FALSE == rc);
1468
if (inconsistentStack) {
1469
constantPool = (J9ROMConstantPoolItem *) (romClass + 1);
1470
utf8string = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[((J9ROMFieldRef *) info)->classRefCPIndex]);
1471
1472
/* Jazz 82615: Store the expected data type for later retrieval in classNameList. */
1473
errorTargetType = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
1474
1475
/* If the error occurs in isFieldAccessCompatible(), the stackTop pointer needs
1476
* to be restored to point to the previous location of receiver (wrong data type) and
1477
* restore the value of receiver if overridden by other data.
1478
*/
1479
if (NULL != receiverPtr) {
1480
stackTop = receiverPtr;
1481
}
1482
*stackTop = receiver;
1483
errorStackIndex = stackTop - liveStack->stackElements;
1484
goto _inconsistentStack;
1485
}
1486
1487
if (receiver != BCV_BASE_TYPE_NULL) {
1488
utf8string = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[((J9ROMFieldRef *) info)->classRefCPIndex]);
1489
1490
rc = isProtectedAccessPermitted (verifyData, utf8string, receiver, (void *) info, TRUE, &reasonCode);
1491
if (FALSE == rc) {
1492
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1493
goto _outOfMemoryError;
1494
}
1495
errorType = J9NLS_BCV_ERR_BAD_ACCESS_PROTECTED__ID;
1496
/* Jazz 82615: Set the error code when error occurs in checking the protected member access. */
1497
verboseErrorCode = BCV_ERR_BAD_ACCESS_PROTECTED;
1498
goto _miscError;
1499
}
1500
}
1501
break;
1502
}
1503
1504
case RTV_SEND:
1505
if ((bc == JBinvokehandle) || (bc == JBinvokehandlegeneric)) {
1506
IDATA reasonCode = 0;
1507
1508
index = PARAM_16(bcIndex, 1);
1509
info = &constantPool[index];
1510
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
1511
/* Removes the args from the stack and verify the stack shape is consistent */
1512
rc = j9rtv_verifyArguments(verifyData, utf8string, &stackTop);
1513
CHECK_STACK_UNDERFLOW;
1514
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
1515
goto _outOfMemoryError;
1516
}
1517
inconsistentStack |= (BCV_SUCCESS != rc);
1518
if (inconsistentStack) {
1519
/* errorDetailCode has been initialized with 0 (SUCCESS) before any verification error is detected
1520
* For the return code from j9rtv_verifyArguments(), there is no need to print out error message framework
1521
* in the case of BCV_FAIL for bad signature (should never happen - caught by cfreader.c in checkMethodSignature)
1522
* and BCV_ERR_INSUFFICIENT_MEMORY for OOM as there is nothing meaningful to show up.
1523
*/
1524
if (verifyData->errorDetailCode < 0) {
1525
J9UTF8 * utf8ClassString = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[((J9ROMMethodRef *) info)->classRefCPIndex]);
1526
J9UTF8 * utf8MethodString = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_NAME(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
1527
storeMethodInfo(verifyData, utf8ClassString, utf8MethodString, utf8string, start);
1528
}
1529
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
1530
goto _verifyError;
1531
}
1532
1533
/* Don't need to do protected access check here - both of these are special
1534
* cases of invokevirtual which only invoke public methods of a public class.
1535
*/
1536
1537
/* Remove the receiver from the stack. */
1538
type = POP;
1539
/* Receiver compatible with MethodHandle? */
1540
rc = isClassCompatibleByName(verifyData, type, (U_8 *)"java/lang/invoke/MethodHandle", sizeof("java/lang/invoke/MethodHandle") - 1, &reasonCode);
1541
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
1542
if ((JBinvokehandle == bc) && (FALSE == rc)) {
1543
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1544
goto _outOfMemoryError;
1545
}
1546
/* Receiver compatible with VarHandle? */
1547
rc = isClassCompatibleByName(verifyData, type, (U_8 *)"java/lang/invoke/VarHandle", sizeof("java/lang/invoke/VarHandle") - 1, &reasonCode);
1548
}
1549
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
1550
if (FALSE == rc) {
1551
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1552
goto _outOfMemoryError;
1553
}
1554
errorType = J9NLS_BCV_ERR_RECEIVER_NOT_COMPATIBLE__ID;
1555
/* Jazz 82615: Store the index of the expected data type 'java/lang/invoke/MethodHandle'
1556
* or 'java/lang/invoke/VarHandle' for later retrieval in classNameList. */
1557
errorTargetType = (UDATA)(BCV_JAVA_LANG_INVOKE_METHODHANDLE_INDEX << BCV_CLASS_INDEX_SHIFT);
1558
errorStackIndex = stackTop - liveStack->stackElements;
1559
goto _inconsistentStack2;
1560
}
1561
stackTop = pushReturnType(verifyData, utf8string, stackTop);
1562
1563
break;
1564
}
1565
1566
if (bc == JBinvokedynamic) {
1567
index = PARAM_16(bcIndex, 1); /* TODO 3 byte index */
1568
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(SRP_PTR_GET(callSiteData + index, J9ROMNameAndSignature*))));
1569
/* Removes the args from the stack and verify the stack shape is consistent */
1570
rc = j9rtv_verifyArguments(verifyData, utf8string, &stackTop);
1571
CHECK_STACK_UNDERFLOW;
1572
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
1573
goto _outOfMemoryError;
1574
}
1575
inconsistentStack |= (BCV_SUCCESS != rc);
1576
if (inconsistentStack) {
1577
/* errorDetailCode has been initialized with 0 (SUCCESS) before any verification error is detected
1578
* For the return code from j9rtv_verifyArguments(), there is no need to print out error message framework
1579
* in the case of BCV_FAIL for bad signature (should never happen - caught by cfreader.c in checkMethodSignature)
1580
* and BCV_ERR_INSUFFICIENT_MEMORY for OOM as there is nothing meaningful to show up.
1581
*/
1582
if (verifyData->errorDetailCode < 0) {
1583
J9UTF8 * utf8ClassString = J9ROMCLASS_CLASSNAME(romClass);
1584
J9UTF8 * utf8MethodString = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_NAME(SRP_PTR_GET(callSiteData + index, J9ROMNameAndSignature*))));
1585
storeMethodInfo(verifyData, utf8ClassString, utf8MethodString, utf8string, start);
1586
}
1587
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
1588
goto _verifyError;
1589
}
1590
stackTop = pushReturnType(verifyData, utf8string, stackTop);
1591
break;
1592
}
1593
1594
if (bc == JBinvokeinterface2) {
1595
bcIndex += 2;
1596
bc = JBinvokeinterface;
1597
}
1598
index = PARAM_16(bcIndex, 1);
1599
if (JBinvokestaticsplit == bc) {
1600
index = *(U_16 *)(J9ROMCLASS_STATICSPLITMETHODREFINDEXES(romClass) + index);
1601
} else if (JBinvokespecialsplit == bc) {
1602
index = *(U_16 *)(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(romClass) + index);
1603
}
1604
info = &constantPool[index];
1605
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
1606
cpIndex = ((J9ROMMethodRef *) info)->classRefCPIndex;
1607
classRef = (J9ROMStringRef *) &constantPool[cpIndex];
1608
rc = j9rtv_verifyArguments(verifyData, utf8string, &stackTop); /* Removes the args from the stack */
1609
CHECK_STACK_UNDERFLOW;
1610
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
1611
goto _outOfMemoryError;
1612
}
1613
inconsistentStack |= (BCV_SUCCESS != rc);
1614
if (inconsistentStack) {
1615
/* errorDetailCode has been initialized with 0 (SUCCESS) before any verification error is detected
1616
* For the return code from j9rtv_verifyArguments(), there is no need to print out error message framework
1617
* in the case of BCV_FAIL for bad signature (should never happen - caught by cfreader.c in checkMethodSignature)
1618
* and BCV_ERR_INSUFFICIENT_MEMORY for OOM as there is nothing meaningful to show up.
1619
*/
1620
if (verifyData->errorDetailCode < 0) {
1621
J9UTF8 * utf8ClassString = J9ROMSTRINGREF_UTF8DATA(classRef);
1622
J9UTF8 * utf8MethodString = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_NAME(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
1623
storeMethodInfo(verifyData, utf8ClassString, utf8MethodString, utf8string, start);
1624
}
1625
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
1626
goto _verifyError;
1627
}
1628
1629
if ((JBinvokestatic != bc)
1630
&& (JBinvokestaticsplit != bc)
1631
) {
1632
IDATA reasonCode = 0;
1633
1634
type = POP; /* Remove the receiver from the stack */
1635
switch (bc) {
1636
case JBinvokespecial:
1637
case JBinvokespecialsplit:
1638
CHECK_STACK_UNDERFLOW;
1639
/* cannot use isInitMethod here b/c invokespecial may be invoking a different <init> method then the one we are in */
1640
if (J9UTF8_DATA(J9ROMNAMEANDSIGNATURE_NAME(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info)))[0] == '<') {
1641
1642
/* This is <init>, verify that this is a NEW or INIT object */
1643
if ((type & BCV_SPECIAL) == 0) {
1644
/* Fail - not an init object */
1645
errorType = J9NLS_BCV_ERR_BAD_INIT__ID;
1646
/* Jazz 82615: Set the expected data type and the location of wrong data type
1647
* on stack when the verification error occurs.
1648
*/
1649
errorTargetType = BCV_SPECIAL_INIT;
1650
errorStackIndex = stackTop - liveStack->stackElements;
1651
goto _inconsistentStack2;
1652
} else {
1653
temp1 = getSpecialType(verifyData, type, code);
1654
if (temp1 & BCV_SPECIAL_INIT) {
1655
/* fail if getSpecialType didn't decode to a non-special type */
1656
errorType = J9NLS_BCV_ERR_ARGUMENTS_INCOMPATIBLE__ID;
1657
/* Jazz 82615: Set the error code, decoded data type (already in temp1) and
1658
* update the stackTopIndex to include the wrong type on stack (already popped out of stack).
1659
*/
1660
verboseErrorCode = BCV_ERR_BAD_INIT_OBJECT;
1661
errorTempData = temp1;
1662
errorStackIndex = stackTop - liveStack->stackElements;
1663
goto _miscError;
1664
}
1665
1666
/* For uninitialized(x), ensure that class @ 'new X' and class of <init> are identical */
1667
if (type & BCV_SPECIAL_NEW) {
1668
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
1669
classIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
1670
if (classIndex != temp1) {
1671
errorType = J9NLS_BCV_ERR_WRONG_INIT_METHOD__ID;
1672
/* Jazz 82615: Set the expected data type, the wrong type on stack and
1673
* the location of wrong data type on stack when the verification error occurs.
1674
*/
1675
errorTargetType = temp1;
1676
*stackTop = classIndex;
1677
errorStackIndex = stackTop - liveStack->stackElements;
1678
goto _inconsistentStack2;
1679
}
1680
}
1681
1682
/* Ensure the <init> method is either for this class or its direct super class */
1683
if (type & BCV_SPECIAL_INIT) {
1684
UDATA superClassIndex = 0;
1685
1686
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
1687
classIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
1688
1689
utf8string = J9ROMCLASS_SUPERCLASSNAME(romClass);
1690
superClassIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
1691
if ((classIndex != temp1) && (classIndex != superClassIndex)) {
1692
errorType = J9NLS_BCV_ERR_WRONG_INIT_METHOD__ID;
1693
/* Jazz 82615: Set the expected data type, the wrong type on stack and
1694
* the location of wrong data type on stack when the verification error occurs.
1695
*/
1696
errorTargetType = temp1;
1697
*stackTop = classIndex;
1698
errorStackIndex = stackTop - liveStack->stackElements;
1699
goto _inconsistentStack2;
1700
}
1701
}
1702
1703
/* This invoke special will make all copies of this "type" on the stack a real
1704
object, find all copies of this object and initialize them */
1705
ptr = temps; /* assumption that stack follows temps */
1706
/* we don't strictly need to walk temps here, the pending stack would be enough */
1707
while (ptr != stackTop) {
1708
if (*ptr == type) {
1709
*ptr = temp1;
1710
}
1711
ptr++;
1712
}
1713
/* Flag the initialization occurred only if its uninitialized_this */
1714
if (type & BCV_SPECIAL_INIT) {
1715
liveStack->uninitializedThis = FALSE;
1716
}
1717
type = temp1;
1718
}
1719
1720
} else { /* non <init> */
1721
/* The JVM converts invokevirtual of final methods in Object to invokespecial.
1722
* For verification purposes, treat these as invokevirtual by falling through.
1723
*/
1724
J9ROMNameAndSignature *nas = J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info);
1725
J9UTF8 *name = J9ROMNAMEANDSIGNATURE_NAME(nas);
1726
J9UTF8 *sig = J9ROMNAMEANDSIGNATURE_SIGNATURE(nas);
1727
if (!methodIsFinalInObject(J9UTF8_LENGTH(name), J9UTF8_DATA(name), J9UTF8_LENGTH(sig), J9UTF8_DATA(sig))) {
1728
utf8string = J9ROMCLASS_CLASSNAME(romClass);
1729
classIndex = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
1730
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
1731
1732
/* the lazy evaluation would guarantee reasonCode reflects the first failure.
1733
* In all three functions, returned boolean value would indicate an error occurred and the reasonCode is set to BCV_ERR_INSUFFICIENT_MEMORY in OOM cases.
1734
* Hence, if any of the 3 conditions should fail, if it is not on OOM as reasonCode would indicate, it must be a verification error.
1735
*/
1736
if ((FALSE == isClassCompatibleByName(verifyData, classIndex, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), &reasonCode))
1737
|| (FALSE == isClassCompatible(verifyData, type, classIndex, &reasonCode))
1738
) {
1739
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1740
goto _outOfMemoryError;
1741
}
1742
errorType = J9NLS_BCV_ERR_BAD_INVOKESPECIAL__ID;
1743
/* Jazz 82615: Set the error code when error occurs in checking the final method. */
1744
verboseErrorCode = BCV_ERR_BAD_INVOKESPECIAL;
1745
goto _miscError;
1746
}
1747
}
1748
} /* fall through */
1749
1750
case JBinvokevirtual:
1751
rc = isProtectedAccessPermitted (verifyData, J9ROMSTRINGREF_UTF8DATA(classRef), type,
1752
J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info), FALSE, &reasonCode);
1753
1754
if (FALSE == rc) {
1755
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1756
goto _outOfMemoryError;
1757
}
1758
errorType = J9NLS_BCV_ERR_BAD_ACCESS_PROTECTED__ID;
1759
/* Jazz 82615: Set the error code when error occurs in checking the protected member access. */
1760
verboseErrorCode = BCV_ERR_BAD_ACCESS_PROTECTED;
1761
goto _miscError;
1762
}
1763
break;
1764
}
1765
1766
if (bc != JBinvokeinterface) {
1767
utf8string = J9ROMSTRINGREF_UTF8DATA(classRef);
1768
1769
rc = isClassCompatibleByName (verifyData, type, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), &reasonCode);
1770
if (FALSE == rc) {
1771
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1772
goto _outOfMemoryError;
1773
}
1774
errorType = J9NLS_BCV_ERR_RECEIVER_NOT_COMPATIBLE__ID;
1775
/* Jazz 82615: Store the index of the expected data type for later retrieval in classNameList */
1776
errorTargetType = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), 0, 0);
1777
errorStackIndex = stackTop - liveStack->stackElements;
1778
goto _inconsistentStack2;
1779
}
1780
} else {
1781
/* Need to ensure that there is at least an Object reference on the stack for the
1782
* invokeinterface receiver. If the top of stack is a base type or TOP, then
1783
* throw a verify error. The check for the receiver to be an interface occurs in
1784
* the invokeinterface bytecode.
1785
* Note: we need to check whether the Object reference on the stack is initialized
1786
* so as to stop an uninitialized object from being addressed here by invokeinterface.
1787
*/
1788
if ((BCV_TAG_BASE_TYPE_OR_TOP == (type & BCV_TAG_MASK))
1789
|| J9_ARE_ANY_BITS_SET(type, BCV_SPECIAL)
1790
) {
1791
errorType = J9NLS_BCV_ERR_RECEIVER_NOT_COMPATIBLE__ID;
1792
/* Jazz 82615: Set the expected data type and the location of wrong data type
1793
* on stack when the verification error occurs.
1794
*/
1795
errorTargetType = BCV_GENERIC_OBJECT;
1796
errorStackIndex = stackTop - liveStack->stackElements;
1797
goto _inconsistentStack2;
1798
}
1799
}
1800
}
1801
1802
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
1803
stackTop = pushReturnType(verifyData, utf8string, stackTop);
1804
break;
1805
1806
case RTV_PUSH_NEW:
1807
switch (bc) {
1808
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1809
case JBaconst_init:
1810
index = PARAM_16(bcIndex, 1);
1811
info = &constantPool[index];
1812
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
1813
stackTop = pushClassType(verifyData, utf8string, stackTop);
1814
break;
1815
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1816
1817
case JBnew:
1818
case JBnewdup:
1819
index = PARAM_16(bcIndex, 1);
1820
info = &constantPool[index];
1821
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
1822
stackTop = pushClassType(verifyData, utf8string, stackTop);
1823
type = POP;
1824
if (J9_ARE_ANY_BITS_SET(type, BCV_ARITY_MASK)) {
1825
errorType = J9NLS_BCV_ERR_BC_NEW_ARRAY__ID;
1826
verboseErrorCode = BCV_ERR_NEW_OJBECT_MISMATCH;
1827
errorTempData = ((type & BCV_ARITY_MASK) >> BCV_ARITY_SHIFT);
1828
goto _miscError;
1829
}
1830
/* put a uninitialized object of the correct type on the stack */
1831
PUSH(BCV_SPECIAL_NEW | (start << BCV_CLASS_INDEX_SHIFT));
1832
break;
1833
1834
case JBnewarray:
1835
POP_TOS_INTEGER; /* pop the size of the array */
1836
if (inconsistentStack) {
1837
/* Jazz 82615: Set the expected data type and the location of wrong data type
1838
* on stack when the verification error occurs.
1839
*/
1840
errorTargetType = BCV_BASE_TYPE_INT;
1841
errorStackIndex = stackTop - liveStack->stackElements;
1842
goto _inconsistentStack;
1843
}
1844
1845
index = PARAM_8(bcIndex, 1);
1846
type = (UDATA) newArrayParamConversion[index];
1847
PUSH(type); /* arity of one implicit */
1848
break;
1849
1850
case JBanewarray:
1851
POP_TOS_INTEGER; /* pop the size of the array */
1852
if (inconsistentStack) {
1853
/* Jazz 82615: Set the expected data type and the location of wrong data type
1854
* on stack when the verification error occurs.
1855
*/
1856
errorTargetType = BCV_BASE_TYPE_INT;
1857
errorStackIndex = stackTop - liveStack->stackElements;
1858
goto _inconsistentStack;
1859
}
1860
1861
index = PARAM_16(bcIndex, 1);
1862
info = &constantPool[index];
1863
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
1864
1865
stackTop = pushClassType(verifyData, utf8string, stackTop);
1866
/* arity is one greater than signature */
1867
type = POP;
1868
/* Check for arity overflow */
1869
if ((type & BCV_ARITY_MASK) == BCV_ARITY_MASK) {
1870
errorType = J9NLS_BCV_ERR_ARRAY_TYPE_MISMATCH__ID;
1871
/* Jazz 82615: Set the error code and the arity in the case of arity overflow. */
1872
verboseErrorCode = BCV_ERR_ARRAY_ARITY_OVERFLOW;
1873
errorTempData = (type & BCV_ARITY_MASK);
1874
goto _miscError;
1875
}
1876
PUSH(( (UDATA)1 << BCV_ARITY_SHIFT) + type);
1877
break;
1878
1879
case JBmultianewarray:
1880
/* points to cp entry for class of object to create */
1881
index = PARAM_16(bcIndex, 1);
1882
i1 = PARAM_8(bcIndex, 3);
1883
1884
if (i1 == 0) {
1885
errorType = J9NLS_BCV_ERR_ARRAY_DIMENSION_MISMATCH__ID;
1886
/* Jazz 82615: Set the error code and the dimension of array if incorrect. */
1887
verboseErrorCode = BCV_ERR_ARRAY_DIMENSION_MISMATCH;
1888
errorTempData = i1;
1889
goto _miscError;
1890
}
1891
1892
if ((stackTop - i1) < stackBase) {
1893
errorType = J9NLS_BCV_ERR_STACK_UNDERFLOW__ID;
1894
/* Jazz 82615: Set the error code when the verification error related to stack underflow occurs */
1895
verboseErrorCode = BCV_ERR_STACK_UNDERFLOW;
1896
/* Given that the actual data type involved has not yet been located through pop operation when stack underflow occurs,
1897
* step back by one slot to the actual data type to be manipulated by the opcode.
1898
*/
1899
errorStackIndex = (stackTop - liveStack->stackElements) - 1;
1900
/* Always set to the location of the 1st data type on 'stack' to show up if stackTop <= stackBase */
1901
if (stackTop <= stackBase) {
1902
errorStackIndex = stackBase - liveStack->stackElements;
1903
}
1904
goto _miscError;
1905
}
1906
1907
for (i2 = 0; i2 < i1; i2++) {
1908
POP_TOS_INTEGER;
1909
if (inconsistentStack) {
1910
/* Jazz 82615: Set the expected data type and the location of wrong data type
1911
* on stack when the verification error occurs.
1912
*/
1913
errorTargetType = BCV_BASE_TYPE_INT;
1914
errorStackIndex = stackTop - liveStack->stackElements;
1915
goto _inconsistentStack;
1916
}
1917
}
1918
1919
info = &constantPool[index];
1920
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
1921
1922
stackTop = pushClassType(verifyData, utf8string, stackTop);
1923
/* Silly test? */
1924
type = POP;
1925
if (type & BCV_TAG_BASE_ARRAY_OR_NULL) {
1926
i1--;
1927
}
1928
if ((type >> BCV_ARITY_SHIFT) < (UDATA) i1) {
1929
errorType = J9NLS_BCV_ERR_ARRAY_DIMENSION_MISMATCH__ID;
1930
/* Jazz 82615: Set the error code when the dimension of array is incorrect. */
1931
verboseErrorCode = BCV_ERR_ARRAY_DIMENSION_MISMATCH;
1932
errorTempData = (type >> BCV_ARITY_SHIFT);
1933
goto _miscError;
1934
}
1935
PUSH(type);
1936
break;
1937
}
1938
break;
1939
1940
case RTV_MISC:
1941
{
1942
IDATA reasonCode = 0;
1943
switch (bc) {
1944
case JBathrow:
1945
POP_TOS_OBJECT(type);
1946
rc = isClassCompatible(verifyData, type, (UDATA) (BCV_JAVA_LANG_THROWABLE_INDEX << BCV_CLASS_INDEX_SHIFT), &reasonCode);
1947
if (FALSE == rc) {
1948
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
1949
goto _outOfMemoryError;
1950
}
1951
errorType = J9NLS_BCV_ERR_NOT_THROWABLE__ID;
1952
/* Jazz 82615: Store the index of the expected data type 'java/lang/invoke/MethodHandle' for later retrieval in classNameList */
1953
errorTargetType = (UDATA)(BCV_JAVA_LANG_THROWABLE_INDEX << BCV_CLASS_INDEX_SHIFT);
1954
errorStackIndex = stackTop - liveStack->stackElements;
1955
1956
/* Jazz 82615: errorType may change in the case of _compatibleError */
1957
if (BCV_ERR_INTERNAL_ERROR == rc) {
1958
goto _compatibleError;
1959
} else {
1960
goto _inconsistentStack2;
1961
}
1962
}
1963
goto _newStack;
1964
break;
1965
1966
case JBarraylength:
1967
POP_TOS_ARRAY(type);
1968
if (inconsistentStack) {
1969
/* Jazz 82615: Given that there is no way to know the information of the expected array type
1970
* (e.g. base/object type, arity, etc), so set the error code (invalid array reference) and
1971
* the location of wrong data type on stack when the verification error occurs.
1972
*/
1973
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
1974
verboseErrorCode = BCV_ERR_INVALID_ARRAY_REFERENCE;
1975
errorTempData = type;
1976
errorStackIndex = stackTop - liveStack->stackElements;
1977
goto _miscError;
1978
}
1979
PUSH_INTEGER_CONSTANT;
1980
break;
1981
1982
case JBtableswitch:
1983
case JBlookupswitch:
1984
POP_TOS_INTEGER;
1985
if (inconsistentStack) {
1986
/* Jazz 82615: Set the expected data type and the location of wrong data type
1987
* on stack when the verification error occurs.
1988
*/
1989
errorTargetType = BCV_BASE_TYPE_INT;
1990
errorStackIndex = stackTop - liveStack->stackElements;
1991
goto _inconsistentStack;
1992
}
1993
index = (UDATA) ((4 - (pc & 3)) & 3); /* consume padding */
1994
pc += index;
1995
bcIndex += index;
1996
pc += 8;
1997
CHECK_END;
1998
offset32 = (I_32) PARAM_32(bcIndex, 1);
1999
bcIndex += 4;
2000
target = offset32 + start;
2001
SAVE_STACKTOP(liveStack, stackTop);
2002
rc = findAndMatchStack (verifyData, target, start);
2003
if (BCV_SUCCESS != rc) {
2004
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
2005
goto _outOfMemoryError;
2006
}
2007
goto _mapError;
2008
}
2009
2010
if (bc == JBtableswitch) {
2011
i1 = (I_32) PARAM_32(bcIndex, 1);
2012
bcIndex += 4;
2013
pc += 4;
2014
i2 = (I_32) PARAM_32(bcIndex, 1);
2015
bcIndex += 4;
2016
2017
pc += ((I_32)i2 - (I_32)i1 + 1) * 4;
2018
CHECK_END;
2019
2020
/* Add the table switch destinations in reverse order to more closely mimic the order that people
2021
(ie: the TCKs) expect you to load classes */
2022
bcIndex += (((I_32)i2 - (I_32)i1) * 4); /* point at the last table switch entry */
2023
2024
/* Count the entries */
2025
i2 = (I_32)i2 - (I_32)i1 + 1;
2026
for (i1 = 0; (I_32)i1 < (I_32)i2; i1++) {
2027
offset32 = (I_32) PARAM_32(bcIndex, 1);
2028
bcIndex -= 4; /* back up to point at the previous table switch entry */
2029
target = offset32 + start;
2030
rc = findAndMatchStack (verifyData, target, start);
2031
if (BCV_SUCCESS != rc) {
2032
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
2033
goto _outOfMemoryError;
2034
}
2035
goto _mapError;
2036
}
2037
}
2038
} else {
2039
BOOLEAN firstKey = TRUE;
2040
I_32 currentKey = 0;
2041
I_32 nextKey = 0;
2042
i2 = (I_32) PARAM_32(bcIndex, 1);
2043
bcIndex += 4;
2044
2045
pc += (I_32)i2 * 8;
2046
CHECK_END;
2047
for (i1 = 0; (I_32)i1 < (I_32)i2; i1++) {
2048
nextKey = (I_32) PARAM_32(bcIndex, 1);
2049
bcIndex += 4;
2050
if (!firstKey) {
2051
if (nextKey <= currentKey) {
2052
verboseErrorCode = BCV_ERR_BYTECODE_ERROR;
2053
storeVerifyErrorData(verifyData, (I_16)verboseErrorCode, (U_32)errorStackIndex, (UDATA)-1, (UDATA)-1, start);
2054
errorType = J9NLS_CFR_ERR_BC_SWITCH_NOT_SORTED__ID;
2055
errorModule = J9NLS_CFR_ERR_BC_SWITCH_NOT_SORTED__MODULE;
2056
goto _verifyError;
2057
}
2058
} else {
2059
firstKey = FALSE;
2060
}
2061
currentKey = nextKey;
2062
2063
offset32 = (I_32) PARAM_32(bcIndex, 1);
2064
bcIndex += 4;
2065
target = offset32 + start;
2066
rc = findAndMatchStack (verifyData, target, start);
2067
if (BCV_SUCCESS != rc) {
2068
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
2069
goto _outOfMemoryError;
2070
}
2071
goto _mapError;
2072
}
2073
}
2074
}
2075
goto _newStack;
2076
break;
2077
2078
case JBmonitorenter:
2079
case JBmonitorexit:
2080
/* Monitor instructions are allowed to accept an uninitialized object */
2081
POP_TOS_OBJECT_IN_MONITOR(type);
2082
if (inconsistentStack) {
2083
/* Jazz 82615: Set the expected data type and the location of wrong data type
2084
* on stack when the verification error occurs.
2085
*/
2086
errorTargetType = BCV_GENERIC_OBJECT;
2087
errorStackIndex = stackTop - liveStack->stackElements;
2088
goto _inconsistentStack;
2089
}
2090
break;
2091
2092
case JBcheckcast:
2093
index = PARAM_16(bcIndex, 1);
2094
POP_TOS_OBJECT(type);
2095
if (inconsistentStack) {
2096
/* Jazz 82615: Set the expected data type and the location of wrong data type
2097
* on stack when the verification error occurs.
2098
*/
2099
errorTargetType = BCV_GENERIC_OBJECT;
2100
errorStackIndex = stackTop - liveStack->stackElements;
2101
goto _inconsistentStack;
2102
}
2103
info = &constantPool[index];
2104
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
2105
stackTop = pushClassType(verifyData, utf8string, stackTop);
2106
break;
2107
2108
case JBinstanceof:
2109
POP_TOS_OBJECT(type);
2110
if (inconsistentStack) {
2111
/* Jazz 82615: Set the expected data type and the location of wrong data type
2112
* on stack when the verification error occurs.
2113
*/
2114
errorTargetType = BCV_GENERIC_OBJECT;
2115
errorStackIndex = stackTop - liveStack->stackElements;
2116
goto _inconsistentStack;
2117
}
2118
PUSH_INTEGER_CONSTANT;
2119
break;
2120
}
2121
break;
2122
}
2123
case RTV_POP_2_PUSH_INT:
2124
POP_TOS_TYPE_EQUAL( type, type1 );
2125
if (inconsistentStack) {
2126
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
2127
* the location of wrong data type on stack when the verification error occurs.
2128
*/
2129
errorTargetType = BCV_BASE_TYPE_TOP;
2130
/* Save the long/double type to errorTempData (verifyData->errorTempData)
2131
* so as to ensure the wrong data type is the 2nd slot of long/double type
2132
* in the error message framework rather than a 'top' type.
2133
*/
2134
errorTempData = type1;
2135
/* The location of wrong data type needs to adjusted back to the right place
2136
* because it pops twice from the stack for the wide type.
2137
*/
2138
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
2139
goto _inconsistentStack;
2140
/* Jazz 82615: the second inconsistent stack case in POP_TOS_TYPE_EQUAL should be addressed here */
2141
} else if (inconsistentStack2) {
2142
errorTargetType = type1;
2143
errorStackIndex = stackTop - liveStack->stackElements;
2144
goto _inconsistentStack;
2145
}
2146
POP_TOS_TYPE_EQUAL( type, type1 );
2147
if (inconsistentStack) {
2148
/* Jazz 82615: Set the 2nd slot of long/double type (already in type1) and
2149
* the location of wrong data type on stack when the verification error occurs.
2150
*/
2151
errorTargetType = BCV_BASE_TYPE_TOP;
2152
/* Save the long/double type to errorTempData (verifyData->errorTempData)
2153
* so as to ensure the wrong data type is the 2nd slot of long/double type
2154
* in the error message framework rather than a 'top' type.
2155
*/
2156
errorTempData = type1;
2157
/* The location of wrong data type needs to adjusted back to the right place
2158
* because it pops twice from the stack for the wide type.
2159
*/
2160
errorStackIndex = (stackTop - liveStack->stackElements) + 1;
2161
goto _inconsistentStack;
2162
/* Jazz 82615: the second inconsistent stack case in POP_TOS_TYPE_EQUAL should be addressed here */
2163
} else if (inconsistentStack2) {
2164
errorTargetType = type1;
2165
errorStackIndex = stackTop - liveStack->stackElements;
2166
goto _inconsistentStack;
2167
}
2168
PUSH_INTEGER_CONSTANT;
2169
break;
2170
2171
case RTV_BYTECODE_POP:
2172
POP_TOS_SINGLE(type);
2173
if (inconsistentStack) {
2174
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2175
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2176
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2177
errorStackIndex = stackTop - liveStack->stackElements;
2178
goto _miscError;
2179
}
2180
break;
2181
2182
case RTV_BYTECODE_POP2:
2183
POP_TOS_PAIR(temp1, temp2);
2184
if (inconsistentStack) {
2185
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2186
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2187
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2188
/* The pair of data types should be printed out once detected as invalid */
2189
errorStackIndex = stackTop - liveStack->stackElements + 1;
2190
goto _miscError;
2191
}
2192
break;
2193
2194
case RTV_BYTECODE_DUP:
2195
POP_TOS_SINGLE(type);
2196
if (inconsistentStack) {
2197
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2198
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2199
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2200
errorStackIndex = stackTop - liveStack->stackElements;
2201
goto _miscError;
2202
}
2203
PUSH(type);
2204
PUSH(type);
2205
break;
2206
2207
case RTV_BYTECODE_DUPX1:
2208
POP_TOS_SINGLE(type);
2209
if (inconsistentStack) {
2210
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2211
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2212
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2213
errorStackIndex = stackTop - liveStack->stackElements;
2214
goto _miscError;
2215
}
2216
POP_TOS_SINGLE(temp1);
2217
if (inconsistentStack) {
2218
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2219
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2220
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2221
errorStackIndex = stackTop - liveStack->stackElements;
2222
goto _miscError;
2223
}
2224
PUSH(type);
2225
PUSH(temp1);
2226
PUSH(type);
2227
break;
2228
2229
case RTV_BYTECODE_DUPX2:
2230
POP_TOS_SINGLE(type);
2231
if (inconsistentStack) {
2232
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2233
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2234
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2235
errorStackIndex = stackTop - liveStack->stackElements;
2236
goto _miscError;
2237
}
2238
POP_TOS_PAIR(temp1, temp2); /* use nverifyPop2 ?? */
2239
if (inconsistentStack) {
2240
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2241
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2242
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2243
/* The pair of data types should be printed out once detected as invalid */
2244
errorStackIndex = stackTop - liveStack->stackElements + 1;
2245
goto _miscError;
2246
}
2247
PUSH(type);
2248
PUSH(temp2);
2249
PUSH(temp1);
2250
PUSH(type);
2251
break;
2252
2253
case RTV_BYTECODE_DUP2:
2254
POP_TOS_PAIR(temp1, temp2);
2255
if (inconsistentStack) {
2256
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2257
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2258
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2259
/* The pair of data types should be printed out once detected as invalid */
2260
errorStackIndex = stackTop - liveStack->stackElements + 1;
2261
goto _miscError;
2262
}
2263
PUSH(temp2);
2264
PUSH(temp1);
2265
PUSH(temp2);
2266
PUSH(temp1);
2267
break;
2268
2269
case RTV_BYTECODE_DUP2X1:
2270
POP_TOS_PAIR(type, temp1);
2271
if (inconsistentStack) {
2272
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2273
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2274
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2275
/* The pair of data types should be printed out once detected as invalid */
2276
errorStackIndex = stackTop - liveStack->stackElements + 1;
2277
goto _miscError;
2278
}
2279
POP_TOS_SINGLE(temp2);
2280
if (inconsistentStack) {
2281
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2282
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2283
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2284
errorStackIndex = stackTop - liveStack->stackElements;
2285
goto _miscError;
2286
}
2287
PUSH(temp1);
2288
PUSH(type);
2289
PUSH(temp2);
2290
PUSH(temp1);
2291
PUSH(type);
2292
break;
2293
2294
case RTV_BYTECODE_DUP2X2:
2295
POP_TOS_PAIR(type, temp1);
2296
if (inconsistentStack) {
2297
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2298
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2299
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2300
/* The pair of data types should be printed out once detected as invalid */
2301
errorStackIndex = stackTop - liveStack->stackElements + 1;
2302
goto _miscError;
2303
}
2304
POP_TOS_PAIR(temp2, temp3);
2305
if (inconsistentStack) {
2306
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2307
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2308
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2309
/* The pair of data types should be printed out once detected as invalid */
2310
errorStackIndex = stackTop - liveStack->stackElements + 1;
2311
goto _miscError;
2312
}
2313
/* should probably do more checking to avoid bogus dup's of long/double pairs */
2314
PUSH(temp1);
2315
PUSH(type);
2316
PUSH(temp3);
2317
PUSH(temp2);
2318
PUSH(temp1);
2319
PUSH(type);
2320
break;
2321
2322
case RTV_BYTECODE_SWAP:
2323
POP_TOS_SINGLE(type);
2324
if (inconsistentStack) {
2325
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2326
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2327
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2328
errorStackIndex = stackTop - liveStack->stackElements;
2329
goto _miscError;
2330
}
2331
POP_TOS_SINGLE(temp1);
2332
if (inconsistentStack) {
2333
/* Jazz 82615: Set the error code (a non-top type is expected on stack). */
2334
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2335
verboseErrorCode = BCV_ERR_WRONG_TOP_TYPE;
2336
errorStackIndex = stackTop - liveStack->stackElements;
2337
goto _miscError;
2338
}
2339
PUSH(type);
2340
PUSH(temp1);
2341
break;
2342
2343
default:
2344
errorType = J9NLS_BCV_ERR_BC_UNKNOWN__ID;
2345
/* Jazz 82615: Set the error code in the case of unrecognized opcode. */
2346
verboseErrorCode = BCV_ERR_BAD_BYTECODE;
2347
goto _miscError;
2348
}
2349
continue;
2350
2351
_newStack:
2352
2353
/* Do I need a new stack? */
2354
if (pc < length) {
2355
2356
/* Do I have more stacks */
2357
if ((UDATA) nextStackPC < length) {
2358
2359
/* Is the next stack for the next bytecode */
2360
if (pc != (UDATA) nextStackPC) {
2361
if (J9ROMCLASS_HAS_VERIFY_DATA(romClass) && (!verifyData->ignoreStackMaps)) {
2362
/* the nextStack is not the wanted stack */
2363
/* Flow verification allows dead code without a map */
2364
/* Jazz 82615: Set the error code, the next pc value, and the pc value of unexpected stackmap frame. */
2365
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2366
verboseErrorCode = BCV_ERR_WRONG_STACKMAP_FRAME;
2367
errorTempData = nextStackPC;
2368
start = pc;
2369
goto _miscError;
2370
} else {
2371
/* skip dead code to nextStackPC */
2372
pc = nextStackPC;
2373
}
2374
}
2375
2376
/* Load the next stack into the live stack */
2377
SAVE_STACKTOP(liveStack, stackTop);
2378
memcpy((UDATA *) liveStack, (UDATA *) currentMapData, verifyData->stackSize);
2379
isNextStack = TRUE;
2380
RELOAD_LIVESTACK;
2381
2382
/* Start with uninitialized_this flag for the current map data */
2383
liveStack->uninitializedThis = currentMapData->uninitializedThis;
2384
2385
/* New next stack */
2386
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
2387
} else {
2388
/* no map available */
2389
if (J9ROMCLASS_HAS_VERIFY_DATA(romClass) && (!verifyData->ignoreStackMaps)) {
2390
/* Flow verification allows dead code without a map */
2391
/* Jazz 82615: Set the error code when nextStackPC goes beyond the stackmap table. */
2392
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2393
verboseErrorCode = BCV_ERR_NO_STACKMAP_FRAME;
2394
errorTempData = (UDATA)nextStackPC;
2395
goto _miscError;
2396
} else {
2397
if ((action != RTV_RETURN)
2398
&& (bc !=JBathrow)
2399
&& (bc !=JBtableswitch)
2400
&& (bc !=JBlookupswitch)
2401
&& (bc !=JBgoto)
2402
&& (bc !=JBgotow)
2403
) {
2404
/* Jazz 82615: Set the error code when it reaches unterminated dead code. */
2405
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2406
verboseErrorCode = BCV_ERR_DEAD_CODE;
2407
goto _miscError;
2408
}
2409
/* no more maps, skip remaining code as dead */
2410
pc = length;
2411
}
2412
}
2413
}
2414
}
2415
2416
/* StackMap/StackMapTable attribute treat all code as live */
2417
/* Flow verification allows unterminated dead code */
2418
if ((action != RTV_RETURN)
2419
&& (bc !=JBathrow)
2420
&& (bc !=JBtableswitch)
2421
&& (bc !=JBlookupswitch)
2422
&& (bc !=JBgoto)
2423
&& (bc !=JBgotow)
2424
) {
2425
/* Jazz 82615: Set the error code when it reaches unterminated dead code. */
2426
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2427
verboseErrorCode = BCV_ERR_DEAD_CODE;
2428
goto _miscError;
2429
}
2430
2431
Trc_RTV_verifyBytecodes_Exit(verifyData->vmStruct);
2432
2433
return BCV_SUCCESS;
2434
#undef CHECK_END
2435
2436
errorType = J9NLS_BCV_ERR_UNEXPECTED_EOF__ID; /* should never reach here */
2437
goto _verifyError;
2438
2439
_mapError:
2440
/* TODO: add tracepoint that indicates a map error occured:
2441
* class, method, pc
2442
*/
2443
2444
errorType = J9NLS_BCV_ERR_INCONSISTENT_STACK__ID;
2445
_compatibleError:
2446
if (rc == BCV_ERR_INTERNAL_ERROR) {
2447
errorType = J9NLS_BCV_ERR_CLASS_LOAD_FAILED__ID;
2448
}
2449
2450
_verifyError:
2451
/* Jazz 82615: Store the error code in the case of CHECK_STACK_UNDERFLOW */
2452
if ((stackTop < stackBase) && (J9NLS_BCV_ERR_STACK_UNDERFLOW__ID == errorType)) {
2453
/* Reset to the location of the 1st data type on 'stack' in the case of stack underflow to show up */
2454
errorStackIndex = stackBase - liveStack->stackElements;
2455
storeVerifyErrorData(verifyData, BCV_ERR_STACK_UNDERFLOW, (U_32)errorStackIndex, (UDATA)-1, (UDATA)-1, start);
2456
}
2457
2458
Trc_RTV_verifyBytecodes_VerifyError(verifyData->vmStruct,
2459
errorType,
2460
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2461
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2462
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2463
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2464
start);
2465
2466
Trc_RTV_verifyBytecodes_VerifyErrorBytecode(verifyData->vmStruct,
2467
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2468
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2469
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2470
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2471
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2472
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2473
errorType, start, start, *(code + start));
2474
BUILD_VERIFY_ERROR(errorModule, errorType);
2475
2476
return BCV_ERR_INTERNAL_ERROR;
2477
2478
_miscError:
2479
/* Jazz 82615: Store the error code and the location of wrong data type on stack in the case of the verification error unrelated to incompatible type */
2480
storeVerifyErrorData(verifyData, (I_16)verboseErrorCode, (U_32)errorStackIndex, (UDATA)-1, errorTempData, start);
2481
goto _verifyError;
2482
2483
_outOfMemoryError:
2484
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
2485
Trc_RTV_verifyBytecodes_OutOfMemoryException(verifyData->vmStruct,
2486
errorType,
2487
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2488
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2489
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2490
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2491
start);
2492
BUILD_VERIFY_ERROR(errorModule, errorType);
2493
return BCV_ERR_INSUFFICIENT_MEMORY;
2494
}
2495
2496
2497
/*
2498
* returns BCV_SUCCESS on success
2499
* returns BCV_FAIL on error
2500
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
2501
*/
2502
static IDATA
2503
verifyExceptions (J9BytecodeVerificationData *verifyData)
2504
{
2505
J9ROMMethod *romMethod = verifyData->romMethod;
2506
J9ROMClass *romClass = verifyData->romClass;
2507
J9ExceptionInfo *exceptionInfo;
2508
J9ExceptionHandler *handler;
2509
J9ROMConstantPoolItem *romConstantPool;
2510
J9UTF8 *catchName;
2511
UDATA i, catchClass;
2512
IDATA rc = BCV_SUCCESS;
2513
IDATA reasonCode = 0;
2514
2515
Trc_RTV_verifyExceptions_Entry(verifyData->vmStruct,
2516
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2517
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2518
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2519
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
2520
2521
/* Verify catch types are throwable */
2522
exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
2523
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
2524
romConstantPool = J9_ROM_CP_FROM_ROM_CLASS(verifyData->romClass);
2525
2526
for (i = 0; i < exceptionInfo->catchCount; i++, handler++) {
2527
if (handler->exceptionClassIndex) {
2528
IDATA tempRC = 0;
2529
2530
catchName = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&romConstantPool [handler->exceptionClassIndex]));
2531
catchClass = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(catchName), J9UTF8_LENGTH(catchName), 0, 0);
2532
tempRC = isClassCompatible (verifyData, catchClass, (UDATA) (BCV_JAVA_LANG_THROWABLE_INDEX << BCV_CLASS_INDEX_SHIFT), &reasonCode);
2533
if (FALSE == tempRC) {
2534
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
2535
Trc_RTV_verifyExceptions_OutOfMemoryException(verifyData->vmStruct,
2536
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2537
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2538
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2539
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2540
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2541
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
2542
rc = BCV_ERR_INSUFFICIENT_MEMORY;
2543
break;
2544
} else {
2545
Trc_RTV_verifyExceptions_VerifyError(verifyData->vmStruct,
2546
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2547
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2548
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2549
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2550
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2551
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2552
i, J9UTF8_LENGTH(catchName), J9UTF8_DATA(catchName));
2553
rc = BCV_FAIL;
2554
break;
2555
}
2556
}
2557
}
2558
}
2559
2560
Trc_RTV_verifyExceptions_Exit(verifyData->vmStruct);
2561
2562
return rc;
2563
}
2564
2565
2566
2567
/*
2568
* returns BCV_SUCCESS on success
2569
* returns BCV_FAIL on errors
2570
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
2571
* TODO: get rid of all the "this should never happen, checked by cfreader.c checks" */
2572
IDATA
2573
j9rtv_verifyArguments (J9BytecodeVerificationData *verifyData, J9UTF8 * utf8string, UDATA ** pStackTop)
2574
{
2575
IDATA argCount, index;
2576
UDATA arity, objectType, baseType;
2577
UDATA *stackTop;
2578
U_8 *signature;
2579
U_16 length;
2580
U_8 *string;
2581
IDATA rc;
2582
IDATA mrc = BCV_SUCCESS;
2583
BOOLEAN boolType = FALSE;
2584
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
2585
2586
Trc_RTV_j9rtv_verifyArguments_Entry(verifyData->vmStruct, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string));
2587
2588
stackTop = *pStackTop;
2589
2590
/* Arguments are in reverse order on the stack, we must pre-pop the stack */
2591
argCount = (IDATA) getSendSlotsFromSignature(J9UTF8_DATA(utf8string));
2592
2593
/*
2594
* Jazz 82615: When the number of arguments is greater than the whole stack size,
2595
* Set stackTop with the address at liveStack->stackElements to avoid compare against garbage that doesn't exist on stack.
2596
*/
2597
if ((IDATA)(stackTop - liveStack->stackElements) < argCount) {
2598
stackTop = liveStack->stackElements;
2599
} else {
2600
stackTop = stackTop - argCount;
2601
}
2602
2603
signature = J9UTF8_DATA(utf8string) + 1; /* skip open bracket */
2604
2605
/* Walk the arguments and verify the stack */
2606
for (index = 0; index < argCount; index++) {
2607
2608
arity = 0;
2609
objectType = 0;
2610
boolType = FALSE;
2611
2612
/* Look for an array */
2613
if (*signature == '[') {
2614
2615
while (*signature == '[') {
2616
signature++;
2617
arity++;
2618
}
2619
2620
}
2621
2622
/* Object or array */
2623
if (IS_REF_OR_VAL_SIGNATURE(*signature) || arity) {
2624
IDATA reasonCode = 0;
2625
2626
/* Object array */
2627
if (IS_REF_OR_VAL_SIGNATURE(*signature)) {
2628
signature++;
2629
string = signature; /* remember the start of the string */
2630
while (*signature++ != ';');
2631
length = (U_16) (signature - string - 1);
2632
objectType = convertClassNameToStackMapType(verifyData, string, length, 0, arity);
2633
2634
/* Base type array */
2635
} else {
2636
2637
if ((*signature < 'A') || (*signature > 'Z')) {
2638
/* Should never happen - bad sig. caught by cfreader.c checkMethodSignature */
2639
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
2640
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2641
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2642
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2643
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2644
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2645
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2646
__LINE__);
2647
mrc = BCV_FAIL;
2648
break;
2649
}
2650
2651
objectType = (UDATA) baseTypeCharConversion[*signature - 'A'];
2652
signature++;
2653
2654
if (!objectType) {
2655
/* Should never happen - bad sig. caught by cfreader.c checkMethodSignature */
2656
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
2657
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2658
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2659
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2660
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2661
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2662
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2663
__LINE__);
2664
mrc = BCV_FAIL;
2665
break;
2666
}
2667
2668
arity--;
2669
objectType |= BCV_TAG_BASE_ARRAY_OR_NULL;
2670
}
2671
2672
/* Check the object */
2673
objectType |= (arity << BCV_ARITY_SHIFT);
2674
rc = isClassCompatible (verifyData, stackTop[index], objectType, &reasonCode);
2675
2676
if (FALSE == rc) {
2677
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
2678
Trc_RTV_j9rtv_verifyArguments_OutOfMemoryException(verifyData->vmStruct,
2679
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2680
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2681
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2682
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2683
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2684
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
2685
mrc = BCV_ERR_INSUFFICIENT_MEMORY;
2686
break;
2687
} else if (BCV_ERR_INACCESSIBLE_CLASS == reasonCode) {
2688
Trc_RTV_j9rtv_verifyArguments_InaccessibleClass(verifyData->vmStruct,
2689
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2690
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2691
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2692
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2693
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2694
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
2695
mrc = BCV_ERR_INACCESSIBLE_CLASS;
2696
break;
2697
} else {
2698
Trc_RTV_j9rtv_verifyArguments_ObjectMismatch(verifyData->vmStruct,
2699
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2700
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2701
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2702
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2703
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2704
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2705
index, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string), stackTop[index]);
2706
mrc = BCV_FAIL;
2707
verifyData->errorDetailCode = BCV_ERR_INCOMPATIBLE_TYPE; /* failure - object type mismatch */
2708
verifyData->errorTargetType = objectType;
2709
break;
2710
}
2711
}
2712
2713
/* Base type */
2714
} else {
2715
2716
if ((*signature < 'A') || (*signature > 'Z')) {
2717
/* Should never happen - bad sig. caught by cfreader.c checkMethodSignature */
2718
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
2719
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2720
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2721
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2722
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2723
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2724
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2725
__LINE__);
2726
mrc = BCV_FAIL;
2727
break;
2728
}
2729
2730
baseType = (UDATA) argTypeCharConversion[*signature - 'A'];
2731
/* Jazz 82615: Tagged as 'bool' when argTypeCharConversion returns BCV_BASE_TYPE_INT for type 'Z'
2732
* Note: for base type, type B (byte) and type Z (boolean) correspond to the verification type int.
2733
* In such case, there is no way to determine whether the original type is byte or boolean after the
2734
* conversion of argument type. To ensure type Z is correctly generated to the error messages, we need
2735
* to filter it out here by checking the type in signature.
2736
*/
2737
if ('Z' == *signature) {
2738
boolType = TRUE;
2739
}
2740
signature++;
2741
2742
if (!baseType) {
2743
/* Should never happen - bad sig. caught by cfreader.c checkMethodSignature */
2744
Trc_RTV_j9rtv_verifyArguments_Unreachable(verifyData->vmStruct,
2745
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2746
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2747
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2748
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2749
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2750
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2751
__LINE__);
2752
mrc = BCV_FAIL;
2753
break;
2754
}
2755
2756
if (stackTop[index] != baseType) {
2757
Trc_RTV_j9rtv_verifyArguments_PrimitiveMismatch(verifyData->vmStruct,
2758
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2759
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2760
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2761
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2762
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2763
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2764
index, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string), stackTop[index]);
2765
mrc = BCV_FAIL;
2766
verifyData->errorDetailCode = BCV_ERR_INCOMPATIBLE_TYPE; /* failure - primitive mismatch */
2767
verifyData->errorTargetType = (TRUE == boolType) ? BCV_BASE_TYPE_BOOL : baseType;
2768
break;
2769
}
2770
2771
if (baseType & BCV_WIDE_TYPE_MASK) {
2772
index++;
2773
if (stackTop[index] != BCV_BASE_TYPE_TOP) {
2774
Trc_RTV_j9rtv_verifyArguments_WidePrimitiveMismatch(verifyData->vmStruct,
2775
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2776
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2777
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2778
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2779
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2780
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2781
index, J9UTF8_LENGTH(utf8string), J9UTF8_DATA(utf8string));
2782
mrc = BCV_FAIL;
2783
verifyData->errorDetailCode = BCV_ERR_INCOMPATIBLE_TYPE; /* failure - wide primitive mismatch */
2784
verifyData->errorTargetType = (TRUE == boolType) ? BCV_BASE_TYPE_BOOL : baseType;
2785
break;
2786
}
2787
}
2788
}
2789
}
2790
2791
/* errorDetailCode has been initialized with 0 (SUCCESS).
2792
* Verification error data related to argument mismatch should be saved here when any verification error is detected above.
2793
*/
2794
if (verifyData->errorDetailCode < 0) {
2795
storeArgumentErrorData(verifyData, (U_32)(&stackTop[index] - liveStack->stackElements), (U_16)index);
2796
}
2797
2798
*pStackTop = stackTop;
2799
2800
Trc_RTV_j9rtv_verifyArguments_Exit(verifyData->vmStruct, mrc);
2801
2802
return mrc;
2803
}
2804
2805
/* Return a pointer to the next stack, update the nextMapIndex and the nextStackPC */
2806
2807
static J9BranchTargetStack *
2808
nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *nextStackPC)
2809
{
2810
J9BranchTargetStack * returnStack = NULL;
2811
/* Default nextStackPC is the end of the method */
2812
*nextStackPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(verifyData->romMethod);
2813
2814
while (*nextMapIndex < (UDATA) verifyData->stackMapsCount) {
2815
returnStack = BCV_INDEX_STACK (*nextMapIndex);
2816
(*nextMapIndex)++;
2817
2818
/* skip unused stack maps */
2819
/* simulateStack can have unused stack map targets - they result from being in dead code */
2820
if (returnStack->stackBaseIndex != -1) {
2821
*nextStackPC = returnStack->pc;
2822
break;
2823
}
2824
}
2825
Trc_RTV_nextStack_Result(verifyData->vmStruct,
2826
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2827
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2828
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2829
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2830
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2831
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2832
verifyData->stackMapsCount, *nextMapIndex, *nextStackPC,
2833
J9_BYTECODE_SIZE_FROM_ROM_METHOD(verifyData->romMethod));
2834
return returnStack;
2835
}
2836
2837
/* Return the next pc in the method that is an exception handler start address */
2838
2839
static IDATA
2840
nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA lastPC)
2841
{
2842
/* Method size */
2843
IDATA nextPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
2844
2845
if (romMethod->modifiers & CFR_ACC_HAS_EXCEPTION_INFO) {
2846
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
2847
J9ExceptionHandler *handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
2848
UDATA i;
2849
2850
for (i = exceptionInfo->catchCount; i; i--, handler++) {
2851
if (((IDATA) handler->startPC) > lastPC) {
2852
if (handler->startPC < (UDATA) nextPC) {
2853
nextPC = handler->startPC;
2854
}
2855
}
2856
}
2857
Trc_RTV_nextExceptionStart_Result(verifyData->vmStruct,
2858
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2859
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2860
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
2861
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
2862
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2863
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2864
exceptionInfo->catchCount, lastPC, nextPC,
2865
J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod));
2866
}
2867
return nextPC;
2868
}
2869
2870
2871
/**
2872
* Store the failure info regarding mismatched argument in method signature to the
2873
* J9BytecodeVerificationData structure for outputting detailed error message
2874
* @param verifyData - pointer to J9BytecodeVerificationData
2875
* @param errorCurrentFramePosition - the location of type data in the current frame when error occurs
2876
* @param errorArgumentIndex - index to the argument of method signature when error occurs
2877
*/
2878
static void
2879
storeArgumentErrorData (J9BytecodeVerificationData * verifyData, U_32 errorCurrentFramePosition, U_16 errorArgumentIndex)
2880
{
2881
verifyData->errorCurrentFramePosition = errorCurrentFramePosition;
2882
verifyData->errorArgumentIndex = errorArgumentIndex;
2883
}
2884
2885
/**
2886
* Postpone storing the method info to the checking of return code after the mismatched argument in method signature is detected
2887
* J9BytecodeVerificationData structure for outputting detailed error message
2888
* @param verifyData - pointer to J9BytecodeVerificationData
2889
* @param errorClassString - pointer to class name
2890
* @param errorMethodString - pointer to method name
2891
* @param errorSignatureString - pointer to signature string
2892
* @param currentPC - current pc value
2893
*/
2894
static void
2895
storeMethodInfo (J9BytecodeVerificationData * verifyData, J9UTF8* errorClassString, J9UTF8* errorMethodString, J9UTF8* errorSignatureString, IDATA currentPC)
2896
{
2897
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
2898
verifyData->errorClassString = errorClassString;
2899
verifyData->errorMethodString = errorMethodString;
2900
verifyData->errorSignatureString = errorSignatureString;
2901
2902
/* Jazz 82615: Set liveStack->pc to the current pc value in the current frame (liveStack)
2903
* info of the detailed error message.
2904
*/
2905
liveStack->pc = (UDATA)currentPC;
2906
}
2907
2908