Skip to content

Commit bf0a639

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 255bc73 commit bf0a639

File tree

1 file changed

+42
-72
lines changed

1 file changed

+42
-72
lines changed

runtime/bcverify/rtverify.c

Lines changed: 42 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+
UDATA tempStoreChange = FALSE;
460460
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
461461
J9ExceptionHandler *handler;
462462
J9UTF8 *catchName;
@@ -520,7 +520,7 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
520520
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
521521

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

525525
/* walk the bytecodes linearly */
526526
while (pc < length) {
@@ -567,8 +567,19 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
567567
currentMapData = nextStack (verifyData, &nextMapIndex, &nextStackPC);
568568
}
569569

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

@@ -579,7 +590,9 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
579590

580591
/* Find all exception handlers from here */
581592
for (i = exceptionInfo->catchCount; i; i--, handler++) {
582-
if (handler->startPC == pc) {
593+
if ((handler->startPC == pc)
594+
|| (tempStoreChange && ((UDATA) start >= handler->startPC) && ((UDATA) start < handler->endPC))
595+
) {
583596
/* Check the maps at the handler PC */
584597
/* Modify the liveStack temporarily to contain the handler exception */
585598
if (handler->exceptionClassIndex) {
@@ -595,7 +608,7 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
595608
PUSH(catchClass);
596609
SAVE_STACKTOP(liveStack, stackTop);
597610

598-
rc = findAndMatchStack (verifyData, handler->handlerPC, start);
611+
rc = findAndMatchStack (verifyData, handler->handlerPC, (tempStoreChange ? pc : start));
599612
if (BCV_SUCCESS != rc) {
600613
if (BCV_ERR_INSUFFICIENT_MEMORY == rc) {
601614
goto _outOfMemoryError;
@@ -609,8 +622,13 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
609622
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
610623
stackTop = originalStackTop;
611624

612-
/* Get next exception start PC of interest */
613-
nextExceptionStartPC = nextExceptionStart (verifyData, romMethod, nextExceptionStartPC);
625+
if (FALSE == tempStoreChange) {
626+
/* Get next exception start PC of interest */
627+
nextExceptionPC (verifyData, romMethod, &exceptionStartPC, &exceptionEndPC);
628+
}
629+
}
630+
if (tempStoreChange) {
631+
tempStoreChange = FALSE;
614632
}
615633

616634
bcIndex = code + pc;
@@ -806,8 +824,6 @@ verifyBytecodes (J9BytecodeVerificationData * verifyData)
806824
goto _inconsistentStack;
807825
}
808826

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

882848
case RTV_ARRAY_STORE:
@@ -2839,22 +2805,24 @@ nextStack (J9BytecodeVerificationData *verifyData, UDATA *nextMapIndex, IDATA *n
28392805
}
28402806

28412807
/* Return the next pc in the method that is an exception handler start address */
2842-
2843-
static IDATA
2844-
nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMethod, IDATA lastPC)
2808+
static void
2809+
nextExceptionPC (J9BytecodeVerificationData* verifyData, J9ROMMethod* romMethod, IDATA* exceptionStartPC, IDATA* exceptionEndPC)
28452810
{
28462811
/* Method size */
2847-
IDATA nextPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
2812+
IDATA nextStartPC = J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
2813+
IDATA nextEndPC = nextStartPC;
28482814

28492815
if (romMethod->modifiers & CFR_ACC_HAS_EXCEPTION_INFO) {
28502816
J9ExceptionInfo *exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
28512817
J9ExceptionHandler *handler = J9EXCEPTIONINFO_HANDLERS(exceptionInfo);
28522818
UDATA i;
28532819

28542820
for (i = exceptionInfo->catchCount; i; i--, handler++) {
2855-
if (((IDATA) handler->startPC) > lastPC) {
2856-
if (handler->startPC < (UDATA) nextPC) {
2857-
nextPC = handler->startPC;
2821+
/* exceptionStartPC has the last exception start. */
2822+
if (((IDATA) handler->startPC) > *exceptionStartPC) {
2823+
if (handler->startPC < (UDATA) nextStartPC) {
2824+
nextStartPC = handler->startPC;
2825+
nextEndPC = handler->endPC;
28582826
}
28592827
}
28602828
}
@@ -2865,10 +2833,12 @@ nextExceptionStart (J9BytecodeVerificationData *verifyData, J9ROMMethod *romMeth
28652833
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
28662834
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
28672835
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
2868-
exceptionInfo->catchCount, lastPC, nextPC,
2836+
exceptionInfo->catchCount, *exceptionStartPC, nextStartPC,
28692837
J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod));
28702838
}
2871-
return nextPC;
2839+
2840+
*exceptionStartPC = nextStartPC;
2841+
*exceptionEndPC = nextEndPC;
28722842
}
28732843

28742844

0 commit comments

Comments
 (0)