Skip to content

Commit 3a6e4b3

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 3a6e4b3

File tree

1 file changed

+51
-72
lines changed

1 file changed

+51
-72
lines changed

runtime/bcverify/rtverify.c

Lines changed: 51 additions & 72 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+
BOOLEAN 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 (!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:
@@ -2862,23 +2828,34 @@ nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *n
28622828
return returnStack;
28632829
}
28642830

2865-
/* 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)
2831+
/**
2832+
* Return the pc range for the next exception handler in romMethod.
2833+
* @param verifyData pointer to J9BytecodeVerificationData
2834+
* @param romMethod the method whose exception handling information is searched
2835+
* @param exceptionStartPC contains the starting pc of the last exception. It will
2836+
* be set to the next exception start pc if one exists otherwise will be set to
2837+
* the last possible pc for the method.
2838+
* @param exceptionEndPC will be set to the next exception end pc if one exists
2839+
* otherwise will be set to the last possible pc for the method.
2840+
*/
2841+
static void
2842+
nextExceptionPC(J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA *exceptionStartPC, IDATA *exceptionEndPC)
28692843
{
28702844
/* Method size */
2871-
IDATA nextPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
2845+
IDATA nextStartPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
2846+
IDATA nextEndPC = nextStartPC;
28722847

28732848
if (romMethod->modifiers & CFR_ACC_HAS_EXCEPTION_INFO) {
28742849
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
28752850
J9ExceptionHandler *handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
28762851
UDATA i;
28772852

28782853
for (i = exceptionInfo->catchCount; i; i--, handler++) {
2879-
if (((IDATA) handler->startPC) > lastPC) {
2880-
if (handler->startPC < (UDATA) nextPC) {
2881-
nextPC = handler->startPC;
2854+
/* exceptionStartPC has the last exception start. */
2855+
if (((IDATA)handler->startPC) > *exceptionStartPC) {
2856+
if (handler->startPC < (UDATA) nextStartPC) {
2857+
nextStartPC = handler->startPC;
2858+
nextEndPC = handler->endPC;
28822859
}
28832860
}
28842861
}
@@ -2889,10 +2866,12 @@ nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMeth
28892866
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
28902867
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
28912868
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2892-
exceptionInfo->catchCount, lastPC, nextPC,
2869+
exceptionInfo->catchCount, *exceptionStartPC, nextStartPC,
28932870
J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod));
28942871
}
2895-
return nextPC;
2872+
2873+
*exceptionStartPC = nextStartPC;
2874+
*exceptionEndPC = nextEndPC;
28962875
}
28972876

28982877

0 commit comments

Comments
 (0)