@@ -7402,13 +7402,36 @@ TR_OpaqueMethodBlock *TR_J9VMBase::getResolvedVirtualMethod(TR_OpaqueClassBlock
74027402 if (isInterfaceClass (classObject))
74037403 return 0 ;
74047404
7405- J9Method *ramMethod = *(J9Method **)((char *)TR ::Compiler->cls .convertClassOffsetToClassPtr (classObject)
7406- + virtualCallOffsetToVTableSlot (virtualCallOffset));
7405+ J9Class *j9class = (J9Class *)TR ::Compiler->cls .convertClassOffsetToClassPtr (classObject);
7406+ UDATA vTableSlot = (UDATA )virtualCallOffsetToVTableSlot (virtualCallOffset);
7407+
7408+ TR ::Compilation *comp = _compInfoPT->getCompilation ();
7409+
7410+ // virtualCallOffset is a vtable slot computed against the class the call was resolved
7411+ // against, while classObject is the receiver's (possibly refined) type. When those
7412+ // differ, such as when an interface accessor whose vtable slot was taken from one
7413+ // implementor which was then refined to a narrower implementor of the same interface,
7414+ // the slot can be out of range of the classObject's vtable, holding an arbitrary
7415+ // non-J9Method value (e.g. a heap object reference).
7416+ J9VTableHeader *vftHeader = J9VTABLE_HEADER_FROM_RAM_CLASS (j9class);
7417+ UDATA vTableNumMethods = vftHeader->size ;
7418+ UDATA firstSlot = sizeof (J9Class) + sizeof (J9VTableHeader);
7419+ UDATA lastSlot = firstSlot + (0 == vTableNumMethods ? 0 : (vTableNumMethods - 1 )) * sizeof (UDATA );
7420+ if ((0 == vTableNumMethods) || (vTableSlot < firstSlot) || (vTableSlot > lastSlot)) {
7421+ OMR ::Logger *log = comp->log ();
7422+ logprintf (comp->getOption (TR_TraceOptDetails), log,
7423+ " getResolvedVirtualMethod: vtable slot %d out of bounds for class %p (vtable holds %d methods, "
7424+ " valid byte range [%d..%d], virtualCallOffset=%d); failing query\n " ,
7425+ (int32_t )vTableSlot, (void *)j9class, (int32_t )vTableNumMethods, (int32_t )firstSlot, (int32_t )lastSlot,
7426+ virtualCallOffset);
7427+ return 0 ;
7428+ }
7429+
7430+ J9Method *ramMethod = *(J9Method **)((char *)j9class + vTableSlot);
74077431
74087432 TR_ASSERT (ramMethod, " getResolvedVirtualMethod should always find a ramMethod in the vtable slot" );
74097433
74107434 // ramMethod might have been inherited from a superclass
7411- TR ::Compilation *comp = _compInfoPT->getCompilation ();
74127435 comp->constProvenanceGraph ()->addEdge (classObject, ramMethod);
74137436
74147437 if (ramMethod && (!(_jitConfig->runtimeFlags & J9JIT_RUNTIME_RESOLVE ) || ignoreRtResolve)
0 commit comments