Skip to content

Commit 9af8c03

Browse files
committed
Check stack map if type changed in the exception table range
J9 has been validating the type state for exceptions after astore changes the type. This is incorrect since according to JVMS 4.10.1.4 the state of a stack map frame is the incoming state of an instruction. This means that the type state of astore is the state before the new local is set. Instead only compare the type state for exceptions if astore changes the type state and another bytecode within the range of the exception exists to make sure its still compatible. Signed-off-by: Theresa Mammarella <[email protected]>
1 parent bda6c42 commit 9af8c03

File tree

1 file changed

+41
-71
lines changed

1 file changed

+41
-71
lines changed

runtime/bcverify/rtverify.c

Lines changed: 41 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static IDATA matchStack (J9BytecodeVerificationData * verifyData, J9BranchTarget
4545
static IDATA findAndMatchStack (J9BytecodeVerificationData *verifyData, IDATA targetPC, IDATA currentPC);
4646
static IDATA verifyExceptions (J9BytecodeVerificationData *verifyData);
4747
static J9BranchTargetStack * nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *nextStackPC);
48-
static IDATA nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA lastPC);
48+
static void nextExceptionPC (J9BytecodeVerificationData* verifyData, J9ROMMethod* romMethod, IDATA* exceptionStartPC, IDATA* exceptionEndPC);
4949
static void storeArgumentErrorData (J9BytecodeVerificationData * verifyData, U_32 errorCurrentFramePosition, U_16 errorArgumentIndex);
5050
static void storeMethodInfo (J9BytecodeVerificationData * verifyData, J9UTF8* errorClassString, J9UTF8* errorMethodString, J9UTF8* errorSignatureString, IDATA currentPC);
5151

@@ -447,16 +447,16 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
447447
UDATA classIndex, maxStack;
448448
UDATA wideIndex = FALSE;
449449
IDATA nextStackPC;
450-
IDATA nextExceptionStartPC;
450+
IDATA exceptionStartPC = -1;
451+
IDATA exceptionEndPC = -1;
451452
IDATA rc = 0;
452453
U_8 returnBytecode;
453454
UDATA errorModule = J9NLS_BCV_ERR_BYTECODES_INVALID__MODULE; /* defaults to BCV NLS catalog */
454455
U_16 errorType;
455456
I_16 offset16;
456457
I_32 offset32;
457458
UDATA argCount;
458-
UDATA checkIfInsideException = romMethod->modifiers & J9AccMethodHasExceptionInfo;
459-
UDATA tempStoreChange;
459+
UDATA tempStoreChange = FALSE;
460460
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
461461
J9ExceptionHandler *handler;
462462
J9UTF8 *catchName;
@@ -523,7 +523,7 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
523523
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
524524

525525
/* Determine where the first region of bytecodes covered by an exception handler is */
526-
nextExceptionStartPC = nextExceptionStart (verifyData, romMethod, -1);
526+
nextExceptionPC (verifyData, romMethod, &exceptionStartPC, &exceptionEndPC);
527527

528528
/* walk the bytecodes linearly */
529529
while (pc < length) {
@@ -570,8 +570,19 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
570570
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
571571
}
572572

573-
/* Check the stack against the exception handler stack */
574-
if (pc == (UDATA) nextExceptionStartPC) {
573+
/* Check the current state against the exception handlers if:
574+
* - This is the first bytecode of the try/catch block
575+
* - The temps (locals) type state has changed due to a store
576+
* instruction. If it is within the same exception range ensure
577+
* that the types are still compatible.
578+
*/
579+
if ((pc == (UDATA) exceptionStartPC)
580+
|| (tempStoreChange && (exceptionStartPC < pc && pc < exceptionEndPC))
581+
) {
582+
/* If this is the first pc of an exception tempStoreChange does not apply. */
583+
if ((pc == (UDATA) exceptionStartPC) && tempStoreChange) {
584+
tempStoreChange = FALSE;
585+
}
575586
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
576587
SAVE_STACKTOP(liveStack, stackTop);
577588

@@ -582,7 +593,9 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
582593

583594
/* Find all exception handlers from here */
584595
for (i = exceptionInfo->catchCount; i; i--, handler++) {
585-
if (handler->startPC == pc) {
596+
if ((handler->startPC == pc)
597+
|| (tempStoreChange && ((UDATA) pc >= handler->startPC) && ((UDATA) pc < handler->endPC))
598+
) {
586599
/* Check the maps at the handler PC */
587600
/* Modify the liveStack temporarily to contain the handler exception */
588601
if (handler->exceptionClassIndex) {
@@ -612,8 +625,13 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
612625
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
613626
stackTop = originalStackTop;
614627

615-
/* Get next exception start PC of interest */
616-
nextExceptionStartPC = nextExceptionStart (verifyData, romMethod, nextExceptionStartPC);
628+
if (FALSE == tempStoreChange) {
629+
/* Get next exception start PC of interest */
630+
nextExceptionPC (verifyData, romMethod, &exceptionStartPC, &exceptionEndPC);
631+
}
632+
}
633+
if (tempStoreChange) {
634+
tempStoreChange = FALSE;
617635
}
618636

619637
bcIndex = code + pc;
@@ -809,8 +827,6 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
809827
goto _inconsistentStack;
810828
}
811829

812-
tempStoreChange = FALSE;
813-
814830
if (type != type1) {
815831
if ((type1 != BCV_GENERIC_OBJECT) || (type & BCV_TAG_BASE_TYPE_OR_TOP)) {
816832
inconsistentStack = TRUE;
@@ -830,56 +846,6 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
830846
}
831847
tempStoreChange |= (type != temps[index]);
832848
STORE_TEMP(index, type);
833-
834-
if (checkIfInsideException && tempStoreChange) {
835-
/* If we've stored a value into an arg/local, and it's of a different type than was
836-
* originally there, we need to ensure that we are still compatible with all our
837-
* exception handlers.
838-
*
839-
* For all exception handlers covering this instruction
840-
*/
841-
handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
842-
SAVE_STACKTOP(liveStack, stackTop);
843-
844-
/* Save the current liveStack element zero */
845-
/* Reset the stack pointer to push the exception on the empty stack */
846-
originalStackTop = stackTop;
847-
originalStackZeroEntry = liveStack->stackElements[liveStack->stackBaseIndex];
848-
849-
/* Find all exception handlers from here */
850-
for (i = exceptionInfo->catchCount; i; i--, handler++) {
851-
if (((UDATA) start >= handler->startPC) && ((UDATA) start < handler->endPC)) {
852-
#ifdef DEBUG_BCV
853-
printf("exception map change check at startPC: %d\n", handler->startPC);
854-
#endif
855-
/* Check the maps at the handler PC */
856-
/* Modify the liveStack temporarily to contain the handler exception */
857-
if (handler->exceptionClassIndex) {
858-
catchName = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&constantPool [handler->exceptionClassIndex]));
859-
catchClass = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(catchName), J9UTF8_LENGTH(catchName), 0, 0);
860-
} else {
861-
catchClass = BCV_JAVA_LANG_THROWABLE_INDEX;
862-
catchClass <<= BCV_CLASS_INDEX_SHIFT;
863-
}
864-
865-
stackTop = &(liveStack->stackElements[liveStack->stackBaseIndex]);
866-
PUSH(catchClass);
867-
SAVE_STACKTOP(liveStack, stackTop);
868-
869-
rc = findAndMatchStack (verifyData, handler->handlerPC, start);
870-
if (BCV_SUCCESS != rc) {
871-
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
872-
goto _outOfMemoryError;
873-
}
874-
goto _mapError;
875-
}
876-
}
877-
}
878-
879-
/* Restore liveStack */
880-
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
881-
stackTop = originalStackTop;
882-
}
883849
break;
884850

885851
case RTV_ARRAY_STORE:
@@ -2863,22 +2829,24 @@ nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *n
28632829
}
28642830

28652831
/* Return the next pc in the method that is an exception handler start address */
2866-
2867-
static IDATA
2868-
nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA lastPC)
2832+
static void
2833+
nextExceptionPC (J9BytecodeVerificationData* verifyData, J9ROMMethod* romMethod, IDATA* exceptionStartPC, IDATA* exceptionEndPC)
28692834
{
28702835
/* Method size */
2871-
IDATA nextPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
2836+
IDATA nextStartPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
2837+
IDATA nextEndPC = nextStartPC;
28722838

28732839
if (romMethod->modifiers & CFR_ACC_HAS_EXCEPTION_INFO) {
28742840
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
28752841
J9ExceptionHandler *handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
28762842
UDATA i;
28772843

28782844
for (i = exceptionInfo->catchCount; i; i--, handler++) {
2879-
if (((IDATA) handler->startPC) > lastPC) {
2880-
if (handler->startPC < (UDATA) nextPC) {
2881-
nextPC = handler->startPC;
2845+
/* exceptionStartPC has the last exception start. */
2846+
if (((IDATA) handler->startPC) > *exceptionStartPC) {
2847+
if (handler->startPC < (UDATA) nextStartPC) {
2848+
nextStartPC = handler->startPC;
2849+
nextEndPC = handler->endPC;
28822850
}
28832851
}
28842852
}
@@ -2889,10 +2857,12 @@ nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMeth
28892857
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
28902858
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
28912859
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2892-
exceptionInfo->catchCount, lastPC, nextPC,
2860+
exceptionInfo->catchCount, *exceptionStartPC, nextStartPC,
28932861
J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod));
28942862
}
2895-
return nextPC;
2863+
2864+
*exceptionStartPC = nextStartPC;
2865+
*exceptionEndPC = nextEndPC;
28962866
}
28972867

28982868

0 commit comments

Comments
 (0)