Path: blob/master/runtime/bcverify/vrfyhelp.c
12575 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#include "bcvcfr.h"23#include "bcverify.h"24#include "bcverify_internal.h"25#include "cfreader.h"26#include "j9protos.h"27#include "j9consts.h"28#include "vrfyconvert.h"29#include "j9cp.h"30#include "j9bcvnls.h"31#include "rommeth.h"32#include "ut_j9bcverify.h"3334#define SUPERCLASS(clazz) ((clazz)->superclasses[ J9CLASS_DEPTH(clazz) - 1 ])35#define J9CLASS_INDEX_FROM_CLASS_ENTRY(clazz) ((clazz & BCV_CLASS_INDEX_MASK) >> BCV_CLASS_INDEX_SHIFT)36#define J9CLASS_ARITY_FROM_CLASS_ENTRY(clazz) (((clazz & BCV_ARITY_MASK) >> BCV_ARITY_SHIFT) + ((clazz & BCV_TAG_BASE_ARRAY_OR_NULL) >> 1))3738#define CLONEABLE_CLASS_NAME "java/lang/Cloneable"39#define SERIALIZEABLE_CLASS_NAME "java/io/Serializable"40#define CLONEABLE_CLASS_NAME_LENGTH (sizeof(CLONEABLE_CLASS_NAME) - 1)41#define SERIALIZEABLE_CLASS_NAME_LENGTH (sizeof(SERIALIZEABLE_CLASS_NAME) - 1)4243static VMINLINE UDATA compareTwoUTF8s (J9UTF8 * first, J9UTF8 * second);44static UDATA addClassName (J9BytecodeVerificationData * verifyData, U_8 * name, UDATA length, UDATA index);45static void getNameAndLengthFromClassNameList (J9BytecodeVerificationData *verifyData, UDATA listIndex, U_8 ** name, UDATA * length);46static IDATA findFieldFromRamClass (J9Class ** ramClass, J9ROMFieldRef * field, UDATA firstSearch);47static IDATA findMethodFromRamClass (J9BytecodeVerificationData * verifyData, J9Class ** ramClass, J9ROMNameAndSignature * method, UDATA firstSearch);48static VMINLINE UDATA * pushType (J9BytecodeVerificationData *verifyData, U_8 * signature, UDATA * stackTop);49static IDATA isRAMClassCompatible(J9BytecodeVerificationData *verifyData, U_8* parentClass, UDATA parentLength, U_8* childClass, UDATA childLength, IDATA *reasonCode);5051J9_DECLARE_CONSTANT_UTF8(j9_vrfy_Object, "java/lang/Object");52J9_DECLARE_CONSTANT_UTF8(j9_vrfy_String, "java/lang/String");53J9_DECLARE_CONSTANT_UTF8(j9_vrfy_Throwable, "java/lang/Throwable");54J9_DECLARE_CONSTANT_UTF8(j9_vrfy_Class, "java/lang/Class");55J9_DECLARE_CONSTANT_UTF8(j9_vrfy_MethodType, "java/lang/invoke/MethodType");56J9_DECLARE_CONSTANT_UTF8(j9_vrfy_MethodHandle, "java/lang/invoke/MethodHandle");575859/* return the new index in the class list table for this name, add it if missing60* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM61*/62static UDATA63addClassName(J9BytecodeVerificationData * verifyData, U_8 * name, UDATA length, UDATA index)64{65J9ROMClass * romClass = verifyData->romClass;66U_32 *offset;67J9UTF8 *utf8;68UDATA classNameInClass = TRUE;69UDATA newSize, i, delta;70U_8 *newBuffer;71PORT_ACCESS_FROM_PORT(verifyData->portLib);7273/* grow the buffers if necessary - will ask for an always conservative amount - assumes classNameInClass = FALSE */74if ((verifyData->classNameSegmentFree + sizeof(UDATA) + sizeof(J9UTF8) + length + sizeof(UDATA)) >= verifyData->classNameSegmentEnd) {75/* Do some magic to grow the classNameSegment. */76newSize = (UDATA) (((length + sizeof(UDATA) + sizeof(J9UTF8) + sizeof(UDATA)) < (32 * (sizeof(UDATA) + sizeof(J9UTF8))))77? (32 * (sizeof(UDATA) + sizeof(J9UTF8)))78: (length + sizeof(UDATA) + sizeof(J9UTF8) + sizeof(UDATA) - 1) & ~(sizeof(UDATA) - 1));79delta = (UDATA) (verifyData->classNameSegmentFree - verifyData->classNameSegment);80newSize += verifyData->classNameSegmentEnd - verifyData->classNameSegment;81newBuffer = j9mem_allocate_memory( newSize , J9MEM_CATEGORY_CLASSES);82if( !newBuffer ) {83return BCV_ERR_INSUFFICIENT_MEMORY; /* fail */84}85verifyData->classNameSegmentFree = newBuffer + delta;86memcpy( newBuffer, verifyData->classNameSegment, (UDATA) (verifyData->classNameSegmentEnd - verifyData->classNameSegment) );87delta = (UDATA) ((newBuffer - verifyData->classNameSegment) / sizeof (J9UTF8));88bcvfree( verifyData, verifyData->classNameSegment );89/* adjust the classNameList for the moved strings */90i = 0;91while (verifyData->classNameList[i]) {92/* Second pass verification can have new strings and preverify data references - move only the new string references */93if (((U_8 *)(verifyData->classNameList[i]) >= verifyData->classNameSegment) && ((U_8 *)(verifyData->classNameList[i]) < verifyData->classNameSegmentEnd)) {94verifyData->classNameList[i] += delta;95}96i++;97}98verifyData->classNameSegment = newBuffer;99verifyData->classNameSegmentEnd = newBuffer + newSize;100}101102if (&(verifyData->classNameList[index + 1]) >= verifyData->classNameListEnd) {103/* Do some magic to grow the classNameList. */104newSize = (UDATA) ((U_8 *) verifyData->classNameListEnd - (U_8 *) verifyData->classNameList + (32 * sizeof(UDATA)));105newBuffer = j9mem_allocate_memory( newSize , J9MEM_CATEGORY_CLASSES);106if( !newBuffer ) {107return BCV_ERR_INSUFFICIENT_MEMORY; /* fail */108}109memcpy( newBuffer, (U_8*) verifyData->classNameList, (UDATA) (((U_8*) verifyData->classNameListEnd) - ((U_8*) verifyData->classNameList)) );110bcvfree( verifyData, verifyData->classNameList );111verifyData->classNameList = (J9UTF8 **) newBuffer;112verifyData->classNameListEnd = (J9UTF8 **) (newBuffer + newSize);113}114115/* Is the new name found in the ROM class? */116if (((UDATA) name < (UDATA) romClass) || ((UDATA) name >= ((UDATA) romClass + (UDATA) romClass->romSize))) {117classNameInClass = FALSE;118}119120offset = (U_32 *) verifyData->classNameSegmentFree;121utf8 = (J9UTF8 *) (offset + 1);122J9UTF8_SET_LENGTH(utf8, (U_16) length);123verifyData->classNameSegmentFree += sizeof(U_32);124if (classNameInClass) {125offset[0] = (U_32) ((UDATA) name - (UDATA) romClass);126verifyData->classNameSegmentFree += sizeof(U_32);127} else {128offset[0] = 0;129strncpy((char *) J9UTF8_DATA(utf8), (char *) name, length);130verifyData->classNameSegmentFree += (sizeof(J9UTF8) + length + sizeof(U_32) - 1) & ~(sizeof(U_32) - 1); /* next U_32 boundary */131}132verifyData->classNameList[index] = (J9UTF8 *) offset;133verifyData->classNameList[index + 1] = NULL;134135136return index;137}138139140141/* Return the new index in the class list table for this name, add it if missing */142143UDATA144findClassName(J9BytecodeVerificationData * verifyData, U_8 * name, UDATA length)145{146J9ROMClass * romClass = verifyData->romClass;147U_32 *offset = NULL;148U_8 *data = NULL;149J9UTF8 *utf8 = NULL;150UDATA index = 0;151152153154while ((offset = (U_32 *) verifyData->classNameList[index]) != NULL) {155utf8 = (J9UTF8 *) (offset + 1);156if ((UDATA) J9UTF8_LENGTH(utf8) == length) {157data = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);158159/* check for identical pointers */160if (data == name) {161return index;162}163164/* handle names found not in the romClass, but in the classNameSegment only */165if (0 == offset[0]) {166data = J9UTF8_DATA(utf8);167}168169if (0 == memcmp(data, name, length)) {170return index;171}172173}174index++;175}176177/* add a class name if not found */178return addClassName(verifyData, name, length, index);179}180181/* Return the encoded stackmap type for the class. add class into class list table if missing */182183UDATA184convertClassNameToStackMapType(J9BytecodeVerificationData * verifyData, U_8 *name, U_16 length, UDATA type, UDATA arity)185{186J9ROMClass * romClass = verifyData->romClass;187U_32 *offset = NULL;188U_8 *data = NULL;189J9UTF8 *utf8 = NULL;190J9UTF8 *utf8_p = NULL;191UDATA index = 0;192193194while ((offset = (U_32 *) verifyData->classNameList[index]) != NULL) {195utf8 = (J9UTF8 *) (offset + 1);196if ((UDATA) J9UTF8_LENGTH(utf8) == (UDATA)length) {197data = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);198199/* check for identical pointers */200if (data == name) {201return type | (index << BCV_CLASS_INDEX_SHIFT);202}203204/* handle names found not in the romClass, but in the classNameSegment only */205if (0 == offset[0]) {206data = J9UTF8_DATA(utf8);207}208209if (0 == memcmp(data, name, (UDATA)length)) {210return type | (index << BCV_CLASS_INDEX_SHIFT);211}212213}214index++;215}216217/* add a class name if not found */218return type | (addClassName(verifyData, name, length, index) << BCV_CLASS_INDEX_SHIFT);219}220221222/**223* @returns BOOLEAN indicating if uninitializedThis is on the stack224*/225BOOLEAN226buildStackFromMethodSignature( J9BytecodeVerificationData *verifyData, UDATA **stackTopPtr, UDATA *argCount)227{228/* @romMethod is a pointer to a romMethod structure229@stackTop is a pointer to a pointer to the start of the stack (grows towards larger values)230231The modified stack is the return result, stackTop is modified accordingly.232*/233const J9ROMClass *romClass = verifyData->romClass;234const J9ROMMethod *romMethod = verifyData->romMethod;235const UDATA argMax = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod);236UDATA i;237U_8 *args;238UDATA arity, baseType;239UDATA classIndex = 0;240UDATA *stackTop;241BOOLEAN isUninitializedThis = FALSE;242243stackTop = *stackTopPtr;244*argCount = 0;245246/* if this is a virtual method, push the receiver */247248if ((!(romMethod->modifiers & J9AccStatic)) && (argMax > 0)) {249/* this is a virtual method, an object compatible with this class is on the stack */250J9UTF8* utf8string = J9ROMMETHOD_NAME(romMethod);251J9UTF8 *className = J9ROMCLASS_CLASSNAME(romClass);252253classIndex = findClassName(verifyData, J9UTF8_DATA(className), J9UTF8_LENGTH(className));254255/* In the <init> method of Object the type of this is Object. In other <init> methods, the type of this is uninitializedThis */256if ((J9UTF8_DATA(utf8string)[0] == '<') && (J9UTF8_DATA(utf8string)[1] == 'i') && (classIndex != BCV_JAVA_LANG_OBJECT_INDEX)) {257/* This is <init>, not java/lang/Object */258PUSH(BCV_SPECIAL_INIT | (classIndex << BCV_CLASS_INDEX_SHIFT));259isUninitializedThis = TRUE;260} else {261PUSH(BCV_GENERIC_OBJECT | (classIndex << BCV_CLASS_INDEX_SHIFT));262}263(*argCount)++;264}265266/* Walk the signature of the method to determine the arg shape */267268args = J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod));269270for (i = 1; args[i] != ')'; i++) {271(*argCount)++;272if ((*argCount) > argMax) {273continue;274}275arity = 0;276while (args[i] == '[') {277i++;278arity++;279}280281if (IS_REF_OR_VAL_SIGNATURE(args[i])) {282U_8 *string;283U_16 length = 0;284285i++;286string = &args[i]; /* remember the start of the string */287while (args[i] != ';') {288i++;289length++;290}291classIndex = convertClassNameToStackMapType(verifyData, string, length, 0, arity);292PUSH(classIndex | (arity << BCV_ARITY_SHIFT));293} else {294if (arity) {295/* Base arrays have implicit arity of 1 */296arity--;297PUSH(BCV_TAG_BASE_ARRAY_OR_NULL | (UDATA) baseTypeCharConversion[args[i] - 'A'] | (arity << BCV_ARITY_SHIFT));298} else {299baseType = (UDATA) argTypeCharConversion[args[i] - 'A'];300PUSH(baseType);301if ((args[i] == 'J') || (args[i] == 'D')) {302(*argCount)++;303PUSH(BCV_BASE_TYPE_TOP);304}305}306}307}308309for (i = 0; i < J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod); i++) {310/* Now push a bunch of uninitialized variables */311PUSH (BCV_BASE_TYPE_TOP);312}313*stackTopPtr = stackTop;314315return isUninitializedThis;316}317318319UDATA*320pushReturnType(J9BytecodeVerificationData *verifyData, J9UTF8 * utf8string, UDATA * stackTop)321{322U_8 *signature;323324/* TODO: Determine if faster to walk utf8string backwards to get the return type as325* there is only 1 return type and potentially many arg types: ie:326* (Ljava/lang/String;II)Ljava/lang/String; is fewer iterations if walking backwards327*328* signature = J9UTF8_DATA(utf8string) + length - 1;329* while (*signature-- != ')');330*/331332signature = J9UTF8_DATA(utf8string);333while (*signature++ != ')');334335return pushType(verifyData, signature, stackTop);336}337338339340UDATA*341pushFieldType(J9BytecodeVerificationData *verifyData, J9UTF8 * utf8string, UDATA *stackTop)342{343return pushType(verifyData, J9UTF8_DATA(utf8string), stackTop);344}345346347348349UDATA *350pushClassType(J9BytecodeVerificationData * verifyData, J9UTF8 * utf8string, UDATA * stackTop)351{352if (J9UTF8_DATA(utf8string)[0] == '[') {353UDATA arrayType = parseObjectOrArrayName(verifyData, J9UTF8_DATA(utf8string));354PUSH(arrayType);355} else {356PUSH(convertClassNameToStackMapType(verifyData, J9UTF8_DATA(utf8string),J9UTF8_LENGTH(utf8string), BCV_OBJECT_OR_ARRAY, 0));357}358359return stackTop;360}361362363364void365initializeClassNameList(J9BytecodeVerificationData *verifyData)366{367J9UTF8 *name;368369/* reset the pointer and zero terminate the class name list */370verifyData->classNameSegmentFree = verifyData->classNameSegment;371verifyData->classNameList[0] = NULL;372373/* Add the "known" classes to the classNameList. The order374* here must exactly match the indexes as listed in bytecodewalk.h.375*/376377/* BCV_JAVA_LANG_OBJECT_INDEX 0 */378name = (J9UTF8*)&j9_vrfy_Object;379findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));380/* BCV_JAVA_LANG_STRING_INDEX 1 */381name = (J9UTF8*)&j9_vrfy_String;382findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));383/* BCV_JAVA_LANG_THROWABLE_INDEX 2 */384name = (J9UTF8*)&j9_vrfy_Throwable;385findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));386/* BCV_JAVA_LANG_CLASS_INDEX 3 */387name = (J9UTF8*)&j9_vrfy_Class;388findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));389/* BCV_JAVA_LANG_INVOKE_METHOD_TYPE_INDEX 4 */390name = (J9UTF8*)&j9_vrfy_MethodType;391findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));392/* BCV_JAVA_LANG_INVOKE_METHODHANDLE_INDEX 5 */393name = (J9UTF8*)&j9_vrfy_MethodHandle;394findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name));395}396397398UDATA *399pushLdcType(J9BytecodeVerificationData *verifyData, J9ROMClass * romClass, UDATA index, UDATA * stackTop)400{401switch(J9_CP_TYPE(J9ROMCLASS_CPSHAPEDESCRIPTION(romClass), index)) {402case J9CPTYPE_CLASS:403PUSH(BCV_JAVA_LANG_CLASS_INDEX << BCV_CLASS_INDEX_SHIFT);404break;405case J9CPTYPE_STRING:406PUSH(BCV_JAVA_LANG_STRING_INDEX << BCV_CLASS_INDEX_SHIFT);407break;408case J9CPTYPE_INT:409PUSH_INTEGER_CONSTANT;410break;411case J9CPTYPE_FLOAT:412PUSH_FLOAT_CONSTANT;413break;414case J9CPTYPE_METHOD_TYPE:415PUSH(BCV_JAVA_LANG_INVOKE_METHOD_TYPE_INDEX << BCV_CLASS_INDEX_SHIFT);416break;417case J9CPTYPE_METHODHANDLE:418PUSH(BCV_JAVA_LANG_INVOKE_METHODHANDLE_INDEX << BCV_CLASS_INDEX_SHIFT);419break;420case J9CPTYPE_CONSTANT_DYNAMIC:421{422J9ROMConstantDynamicRef* romConstantDynamicRef = (J9ROMConstantDynamicRef *)(J9_ROM_CP_FROM_ROM_CLASS(romClass) + index);423J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMCONSTANTDYNAMICREF_NAMEANDSIGNATURE(romConstantDynamicRef));424/* The signature referenced by a ConstantDynamic entry is a field descriptor */425stackTop = pushType(verifyData, J9UTF8_DATA(signature), stackTop);426}427break;428}429430return stackTop;431}432433434435/*436* NOTE:437* targetClass must be:438* - null439* - an object440* - an array of objects441* - an array of base types442* sourceClass can be any valid type descriptor, including NULL, base types, and special objects443*444* returns TRUE if class are compatible445* returns FALSE if class are NOT compatible446* isInterfaceClass() or isRAMClassCompatible() sets reasonCode to BCV_ERR_INSUFFICIENT_MEMORY in OOM447*/448449IDATA450isClassCompatible(J9BytecodeVerificationData *verifyData, UDATA sourceClass, UDATA targetClass, IDATA *reasonCode)451{452UDATA sourceIndex, targetIndex;453UDATA sourceArity, targetArity;454IDATA rc;455U_8 *sourceName, *targetName;456UDATA sourceLength, targetLength;457458/* Record class relationship if -XX:+ClassRelationshipVerifier is used */459BOOLEAN classRelationshipVerifierEnabled = J9_ARE_ANY_BITS_SET(verifyData->vmStruct->javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_CLASS_RELATIONSHIP_VERIFIER);460461*reasonCode = 0;462463/* if they are identical, then we're done */464if( sourceClass == targetClass ) {465return (IDATA) TRUE;466}467468/* NULL is magically compatible */469if( sourceClass == BCV_BASE_TYPE_NULL ) {470return (IDATA) TRUE;471}472473/* Covers the following cases:474* 1) Objects are not compatible with base types475* 2) uninitialized(x) can only merge to itself (covered by srcClass == trgClass check)476* 3) uninitialized_this can only merge to itself (covered by srcClass == trgClass check)477*/478if( sourceClass & BCV_BASE_OR_SPECIAL ) {479return (IDATA) FALSE;480}481482/* if the target is java/lang/Object, we're done */483if( targetClass == (BCV_JAVA_LANG_OBJECT_INDEX << BCV_CLASS_INDEX_SHIFT) ) {484return (IDATA) TRUE;485}486487/* only NULL is compatible with NULL */488if ( targetClass == BCV_BASE_TYPE_NULL ) {489return (IDATA) FALSE;490}491492sourceArity = J9CLASS_ARITY_FROM_CLASS_ENTRY(sourceClass);493targetArity = J9CLASS_ARITY_FROM_CLASS_ENTRY(targetClass);494495/* You can't cast to a larger arity */496if( targetArity > sourceArity ) {497return (IDATA) FALSE;498}499500/* load up the indices, but be aware that these might be base type arrays */501sourceIndex = J9CLASS_INDEX_FROM_CLASS_ENTRY(sourceClass);502targetIndex = J9CLASS_INDEX_FROM_CLASS_ENTRY(targetClass);503504if( targetArity < sourceArity ) {505/* if target is an interface, or an object -- but we need to make sure its not a base type array */506if (targetClass & BCV_TAG_BASE_ARRAY_OR_NULL) {507return (IDATA) FALSE;508}509510if (targetIndex == BCV_JAVA_LANG_OBJECT_INDEX) {511return (IDATA) TRUE;512}513514getNameAndLengthFromClassNameList (verifyData, targetIndex, &targetName, &targetLength);515516/* Jazz 109803: Java 8 VM Spec at 4.10.1.2 Verification Type System says:517* For assignments, interfaces are treated like Object.518* isJavaAssignable(class(_, _), class(To, L)) :- loadedClass(To, L, ToClass), classIsInterface(ToClass).519* isJavaAssignable(From, To) :- isJavaSubclassOf(From, To).520*521* Array types are subtypes of Object. The intent is also that array types522* are subtypes of Cloneable and java.io.Serializable.523* isJavaAssignable(arrayOf(_), class('java/lang/Object', BL)) :- isBootstrapLoader(BL).524* isJavaAssignable(arrayOf(_), X) :- isArrayInterface(X).525* isArrayInterface(class('java/lang/Cloneable', BL)) :- isBootstrapLoader(BL).526* isArrayInterface(class('java/io/Serializable', BL)) :- isBootstrapLoader(BL).527*528* According to the statements above, it emphasizes two cases from the code perspective:529* 1) if the arity of both sourceClass and targetClass is 0,530* then targetClass (ToClass) should be an interface for compatibility.531* 2) if not the case and sourceClass is an array type (sourceArity > 0),532* array type can't be assigned to arbitrary interface or array of interface533* except Object (already checked above), java/lang/Cloneable and java/io/Serializable,534* which means targetClass must be one/array of Object, java/lang/Cloneable and java/io/Serializable.535*/536if (J9UTF8_DATA_EQUALS(targetName, targetLength, CLONEABLE_CLASS_NAME, CLONEABLE_CLASS_NAME_LENGTH)537|| J9UTF8_DATA_EQUALS(targetName, targetLength, SERIALIZEABLE_CLASS_NAME, SERIALIZEABLE_CLASS_NAME_LENGTH)538) {539rc = isInterfaceClass(verifyData, targetName, targetLength, reasonCode);540541if ((classRelationshipVerifierEnabled) && (BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED == *reasonCode)) {542getNameAndLengthFromClassNameList (verifyData, sourceIndex, &sourceName, &sourceLength);543rc = j9bcv_recordClassRelationship (verifyData->vmStruct, verifyData->classLoader, sourceName, sourceLength, targetName, targetLength, reasonCode);544}545546return rc;547}548549return (IDATA) FALSE;550}551552/* At this point we know the arity is equal -- see if either is a base type array */553if( (sourceClass & BCV_TAG_BASE_ARRAY_OR_NULL) || (targetClass & BCV_TAG_BASE_ARRAY_OR_NULL) ) {554/* then they should have been identical, so fail */555return (IDATA) FALSE;556}557558if (targetIndex == BCV_JAVA_LANG_OBJECT_INDEX) {559return (IDATA) TRUE;560}561562getNameAndLengthFromClassNameList (verifyData, targetIndex, &targetName, &targetLength);563564/* if the target is an interface, be permissive */565rc = isInterfaceClass(verifyData, targetName, targetLength, reasonCode);566567getNameAndLengthFromClassNameList (verifyData, sourceIndex, &sourceName, &sourceLength);568569/* classRelationshipVerifierEnabled and target not already loaded, so record the class relationship */570if ((classRelationshipVerifierEnabled) && (BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED == *reasonCode)) {571rc = j9bcv_recordClassRelationship(verifyData->vmStruct, verifyData->classLoader, sourceName, sourceLength, targetName, targetLength, reasonCode);572}573574if ((IDATA) FALSE != rc) {575return rc;576}577578if (NULL != verifyData->vmStruct->currentException) {579return (IDATA) FALSE;580}581582if (J9ROMCLASS_IS_HIDDEN(verifyData->romClass)) {583J9UTF8* className = J9ROMCLASS_CLASSNAME(verifyData->romClass);584if (J9UTF8_DATA_EQUALS(J9UTF8_DATA(className), J9UTF8_LENGTH(className), sourceName, sourceLength)) {585/* isRAMClassCompatible() cannot find ram class of a hidden class, we are testing if586* the source class is the subclass of target class. We can use superclass of source class instead here.587* A hidden class can not be super class of another class, the hidden class name it is not findable and its name is generated at runtime.588*/589J9UTF8* superClassName = J9ROMCLASS_SUPERCLASSNAME(verifyData->romClass);590sourceLength = J9UTF8_LENGTH(superClassName);591sourceName = J9UTF8_DATA(superClassName);592}593}594595rc = isRAMClassCompatible(verifyData, targetName, targetLength , sourceName, sourceLength, reasonCode);596597/* classRelationshipVerifierEnabled and source and/or target not already loaded, so record the class relationship */598if ((classRelationshipVerifierEnabled) && (BCV_ERR_CLASS_RELATIONSHIP_RECORD_REQUIRED == *reasonCode)) {599rc = j9bcv_recordClassRelationship(verifyData->vmStruct, verifyData->classLoader, sourceName, sourceLength, targetName, targetLength, reasonCode);600}601602return rc;603}604605/*606API607@verifyData - internal data structure608@parentClass - U_8 pointer to parent class name609@parentLength - UDATA length of parent class name610@childClass - U_8 pointer to child class name611@childLength - UDATA length of child class name612613If the parentClass is not a super class of the child class, answer FALSE, otherwise answer TRUE.614When FALSE, reasonCode (set by j9rtv_verifierGetRAMClass) is615BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case616617618*/619static IDATA620isRAMClassCompatible(J9BytecodeVerificationData *verifyData, U_8* parentClass, UDATA parentLength, U_8* childClass, UDATA childLength, IDATA *reasonCode)621{622J9Class *sourceRAMClass, *targetRAMClass;623624/* Go get the ROM class for the source and target */625targetRAMClass = j9rtv_verifierGetRAMClass( verifyData, verifyData->classLoader, parentClass, parentLength, reasonCode );626if (NULL == targetRAMClass) {627return FALSE;628}629630/* if the target is an interface, be permissive */631if( targetRAMClass->romClass->modifiers & J9AccInterface ) {632return (IDATA) TRUE;633}634635sourceRAMClass = j9rtv_verifierGetRAMClass( verifyData, verifyData->classLoader, childClass, childLength, reasonCode );636if (NULL == sourceRAMClass) {637return FALSE;638}639640targetRAMClass = J9_CURRENT_CLASS(targetRAMClass);641return isSameOrSuperClassOf( targetRAMClass, sourceRAMClass );642}643644645/*646API647@verifyData - internal data structure648@className - U_8 pointer to class name649@classLength - UDATA length of class name650651If class is an interface answer TRUE, otherwise answer FALSE.652When FALSE, reasonCode (set by j9rtv_verifierGetRAMClass) is653BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case654655656*/657IDATA658isInterfaceClass(J9BytecodeVerificationData * verifyData, U_8* className, UDATA classLength, IDATA *reasonCode)659{660J9Class *ramClass;661662*reasonCode = 0;663664ramClass = j9rtv_verifierGetRAMClass(verifyData, verifyData->classLoader, className, classLength, reasonCode);665if (NULL == ramClass) {666return FALSE;667}668669/* if the target is an interface, be permissive */670if (ramClass->romClass->modifiers & J9AccInterface) {671return TRUE;672}673674return FALSE;675}676677678static UDATA *679pushType(J9BytecodeVerificationData *verifyData, U_8 * signature, UDATA * stackTop)680{681if (*signature != 'V') {682if ((*signature == '[') || IS_REF_OR_VAL_SIGNATURE(*signature)) {683PUSH(parseObjectOrArrayName(verifyData, signature));684} else {685UDATA baseType = (UDATA) argTypeCharConversion[*signature - 'A'];686PUSH(baseType);687if ((*signature == 'J') || (*signature == 'D')) {688PUSH(BCV_BASE_TYPE_TOP);689}690}691}692693return stackTop;694}695696697698/*699* decode the 'special' type described by type, and answer it's normal type.700* If type is not a NEW or INIT object, return type unchanged701*/702703UDATA704getSpecialType(J9BytecodeVerificationData *verifyData, UDATA type, U_8* bytecodes)705{706J9ROMClass * romClass = verifyData->romClass;707J9UTF8* newClassUTF8;708709/* verify that this is a NEW object */710if ((type & BCV_SPECIAL_NEW) == (UDATA) (BCV_SPECIAL_NEW)) {711/* Lookup the Class from the cpEntry used in the 'JBnew' bytecode */712U_8* bcTempPtr;713U_16 index;714J9ROMConstantPoolItem* constantPool;715716bcTempPtr = bytecodes + ((type & BCV_CLASS_INDEX_MASK) >> BCV_CLASS_INDEX_SHIFT);717718index = PARAM_16(bcTempPtr, 1);719720constantPool = (J9ROMConstantPoolItem *) ((U_8 *) romClass + sizeof(J9ROMClass));721newClassUTF8 = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) (&constantPool[index]));722} else {723/* verify that this is an INIT object and un-tag it */724if ((type & BCV_SPECIAL_INIT) == (UDATA) (BCV_SPECIAL_INIT)) {725newClassUTF8 = J9ROMCLASS_CLASSNAME(romClass);726} else {727return type;728}729}730731return convertClassNameToStackMapType(verifyData, J9UTF8_DATA(newClassUTF8), J9UTF8_LENGTH(newClassUTF8), 0, 0);732}733734735/*736* Validates classes compatibility by their name737*738* returns TRUE if class are compatible739* returns FALSE it not compatible740* reasonCode (set by isClassCompatible) is:741* BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case742*/743IDATA744isClassCompatibleByName(J9BytecodeVerificationData *verifyData, UDATA sourceClass, U_8* targetClassName, UDATA targetClassNameLength, IDATA *reasonCode)745{746UDATA index;747748*reasonCode = 0;749750/* NULL is magically compatible */751if( sourceClass == BCV_BASE_TYPE_NULL )752return (IDATA) TRUE;753754/* If the source is special, or a base type -- fail */755if( sourceClass & BCV_BASE_OR_SPECIAL )756return (IDATA) FALSE;757758if (*targetClassName == '[') {759index = parseObjectOrArrayName(verifyData, targetClassName);760} else {761index = convertClassNameToStackMapType(verifyData, targetClassName, (U_16)targetClassNameLength, 0, 0);762}763764return isClassCompatible(verifyData, sourceClass, index, reasonCode);765}766767768769/* This function is used by the bytecode verifier */770771U_8 *772j9bcv_createVerifyErrorString(J9PortLibrary * portLib, J9BytecodeVerificationData * error)773{774const char *formatString;775const char *errorString;776U_8 *verifyError;777UDATA stringLength = 0;778/* Jazz 82615: Statistics data indicates the buffer size of 97% JCK cases is less than 1K */779U_8 byteArray[1024];780U_8* detailedErrMsg = NULL;781UDATA detailedErrMsgLength = 0;782783PORT_ACCESS_FROM_PORT(portLib);784785if ((IDATA) error->errorCode == -1) {786/* We were called with an uninitialized buffer, just return a generic error */787return NULL;788}789790if ((IDATA)error->errorModule == -1) {791return NULL;792}793794if ((IDATA) error->errorPC == -1) {795/* J9NLS_BCV_ERROR_TEMPLATE_NO_PC=%1$s; class=%3$.*2$s, method=%5$.*4$s%7$.*6$s */796formatString = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_BCV_ERROR_TEMPLATE_NO_PC, "%s; class=%.*s, method=%.*s%.*s");797} else {798/* Jazz 82615: Generate the error message framework by default.799* The error message framework is not required when the -XX:-VerifyErrorDetails option is specified.800*/801if (J9_ARE_ALL_BITS_SET(error->verificationFlags, J9_VERIFY_ERROR_DETAILS)802&& (0 != error->errorDetailCode)803) {804/* Jazz 82615: The value of detailedErrMsg may change if the initial byteArray is insufficient to contain the error message framework.805* Under such circumstances, it points to the address of newly allocated memory.806*/807detailedErrMsg = byteArray;808detailedErrMsgLength = sizeof(byteArray);809/* In the case of failure to allocating memory in building the error message framework,810* detailedErrMsg is set to NULL and detailedErrMsgLength is set to 0 on return from getRtvExceptionDetails().811* Therefore, it ends up with a simple error message as the buffer for the error message framework has been cleaned up.812*/813detailedErrMsg = error->javaVM->verboseStruct->getRtvExceptionDetails(error, detailedErrMsg, &detailedErrMsgLength);814}815816/*Jazz 82615: fetch the corresponding NLS message when type mismatch error is detected */817if (NULL == error->errorSignatureString) {818/* J9NLS_BCV_ERROR_TEMPLATE_WITH_PC=%1$s; class=%3$.*2$s, method=%5$.*4$s%7$.*6$s, pc=%8$u */819formatString = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_BCV_ERROR_TEMPLATE_WITH_PC, "%s; class=%.*s, method=%.*s%.*s, pc=%u");820} else {821/*Jazz 82615: J9NLS_BCV_ERROR_TEMPLATE_TYPE_MISMATCH=%1$s; class=%3$.*2$s, method=%5$.*4$s%7$.*6$s, pc=%8$u; Type Mismatch, argument %9$d in signature %11$.*10$s.%13$.*12$s:%15$.*14$s does not match */822formatString = j9nls_lookup_message(J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, J9NLS_BCV_ERROR_TEMPLATE_TYPE_MISMATCH,823"%s; class=%.*s, method=%.*s%.*s, pc=%u; Type Mismatch, argument %d in signature %.*s.%.*s:%.*s does not match");824}825}826827/* Determine the size of the error string we need to allocate */828errorString = OMRPORT_FROM_J9PORT(PORTLIB)->nls_lookup_message(OMRPORT_FROM_J9PORT(PORTLIB), J9NLS_DO_NOT_APPEND_NEWLINE, (U_32)(error->errorModule), (U_32)(error->errorCode), NULL);829stringLength = strlen(errorString);830831stringLength += J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(error->romClass));832stringLength += J9UTF8_LENGTH(J9ROMMETHOD_NAME(error->romMethod));833stringLength += J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(error->romMethod));834stringLength += 10; /* for the PC */835if (NULL != error->errorSignatureString) {836stringLength += 10; /* for the argument index */837stringLength += J9UTF8_LENGTH(error->errorClassString);838stringLength += J9UTF8_LENGTH(error->errorMethodString);839stringLength += J9UTF8_LENGTH(error->errorSignatureString);840}841stringLength += strlen(formatString);842stringLength += detailedErrMsgLength;843844verifyError = j9mem_allocate_memory(stringLength, J9MEM_CATEGORY_CLASSES);845if (NULL != verifyError) {846UDATA errStrLength = 0;847J9UTF8 * romClassName = J9ROMCLASS_CLASSNAME(error->romClass);848J9UTF8 * romMethodName = J9ROMMETHOD_NAME(error->romMethod);849J9UTF8 * romMethodSignatureString = J9ROMMETHOD_SIGNATURE(error->romMethod);850851if (NULL == error->errorSignatureString) {852errStrLength = j9str_printf(PORTLIB, (char*) verifyError, stringLength, formatString, errorString,853(U_32) J9UTF8_LENGTH(romClassName), J9UTF8_DATA(romClassName),854(U_32) J9UTF8_LENGTH(romMethodName), J9UTF8_DATA(romMethodName),855(U_32) J9UTF8_LENGTH(romMethodSignatureString), J9UTF8_DATA(romMethodSignatureString),856error->errorPC);857} else {858/* Jazz 82615: Print the corresponding NLS message to buffer for type mismatch error */859errStrLength = j9str_printf(PORTLIB, (char*) verifyError, stringLength, formatString, errorString,860(U_32) J9UTF8_LENGTH(romClassName), J9UTF8_DATA(romClassName),861(U_32) J9UTF8_LENGTH(romMethodName), J9UTF8_DATA(romMethodName),862(U_32) J9UTF8_LENGTH(romMethodSignatureString), J9UTF8_DATA(romMethodSignatureString),863error->errorPC,864error->errorArgumentIndex,865(U_32) J9UTF8_LENGTH(error->errorClassString), J9UTF8_DATA(error->errorClassString),866(U_32) J9UTF8_LENGTH(error->errorMethodString), J9UTF8_DATA(error->errorMethodString),867(U_32) J9UTF8_LENGTH(error->errorSignatureString), J9UTF8_DATA(error->errorSignatureString));868}869870/* Jazz 82615: Print the error message framework to the existing error buffer */871if (detailedErrMsgLength > 0) {872j9str_printf(PORTLIB, (char*)&verifyError[errStrLength], stringLength - errStrLength, "%.*s", detailedErrMsgLength, detailedErrMsg);873}874}875876/* Jazz 82615: Release the memory pointed by detailedErrMsg if allocated with new memory in getRtvExceptionDetails */877if (detailedErrMsg != byteArray) {878j9mem_free_memory(detailedErrMsg);879}880881/* reset the error buffer */882RESET_VERIFY_ERROR(error);883884return verifyError;885}886887/*888* Validates field access compatibility889*890* returns TRUE if class are compatible891* returns FALSE it not compatible892* reasonCode (set by isClassCompatibleByName) is:893* BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case894*/895IDATA896isFieldAccessCompatible(J9BytecodeVerificationData * verifyData, J9ROMFieldRef * fieldRef, UDATA bytecode, UDATA receiver, IDATA *reasonCode)897{898J9ROMClass * romClass = verifyData->romClass;899J9ROMConstantPoolItem * constantPool = (J9ROMConstantPoolItem *) (romClass + 1);900J9UTF8 * utf8string = J9ROMCLASSREF_NAME((J9ROMClassRef *) &constantPool[fieldRef->classRefCPIndex]);901902*reasonCode = 0;903904if (bytecode == 181) {/* JBputfield */905if ((receiver & BCV_SPECIAL_INIT) == (UDATA) BCV_SPECIAL_INIT) {906J9UTF8 *classString = ((J9UTF8 *) J9ROMCLASS_CLASSNAME(romClass));907if (utf8string != classString) {908/* The following test is not necessary if the class name is uniquely referenced in a class */909if (J9UTF8_LENGTH(utf8string) == J9UTF8_LENGTH(classString)) {910IDATA i;911912/* Reversed scan typically faster for inequality - most classes share common prefixes */913for (i = (IDATA) (J9UTF8_LENGTH(utf8string) - 1); i >= 0; i--) {914if (J9UTF8_DATA(utf8string)[i] != J9UTF8_DATA(classString)[i]) {915break;916}917}918/* check for comparison success */919if (i < 0) {920return (IDATA) TRUE;921}922}923return (IDATA) FALSE;924} else {925return (IDATA) TRUE;926}927}928}929return isClassCompatibleByName(verifyData, receiver, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string), reasonCode);930}931932/* Determine if protected member access is permitted.933* currentClass is the current class934* declaringClass is the class which defines the member935* targetClass is the class for which the member is being used936* member: either a J9ROMFieldRef* or a J9ROMNameAndSignature*937*938* returns TRUE if protected access is permitted,939* returns FALSE if protected access is not permitted940* reasonCode (set by j9rtv_verifierGetRAMClass) is :941* BCV_ERR_INSUFFICIENT_MEMORY if OOM is encountered942*/943944UDATA945isProtectedAccessPermitted(J9BytecodeVerificationData *verifyData, J9UTF8* declaringClassName, UDATA targetClass, void* member, UDATA isField, IDATA *reasonCode )946{947J9ROMClass * romClass = verifyData->romClass;948949*reasonCode = 0;950951/* for performance reasons, don't do protection checks unless -Xfuture or -Xverify:doProtectedAccessCheck is specified */952if ((0 == (verifyData->vmStruct->javaVM->runtimeFlags & J9RuntimeFlagXfuture))953&& (0 == (verifyData->verificationFlags & J9_VERIFY_DO_PROTECTED_ACCESS_CHECK))954) {955return TRUE;956}957958/* Skip protection checks for arrays, they are in the NULL package */959if (J9CLASS_ARITY_FROM_CLASS_ENTRY(targetClass) == 0) {960J9Class * definingRamClass;961J9Class * currentRamClass;962J9UTF8 * currentClassName;963IDATA rc;964965/* Short circuit if the classes are the same */966currentClassName = J9ROMCLASS_CLASSNAME(romClass);967if (compareTwoUTF8s(declaringClassName, currentClassName)) {968return TRUE;969}970if (J9ROMCLASS_IS_HIDDEN(romClass)) {971/* j9rtv_verifierGetRAMClass won't find hidden classes. We are checking if the current class has access to972* proected memeber of declaringClass. We can use the superclass of current class instead here. */973currentClassName = J9ROMCLASS_SUPERCLASSNAME(romClass);974if (compareTwoUTF8s(declaringClassName, currentClassName)) {975return TRUE;976}977}978/* Get the ram classes for the current and defining classes */979currentRamClass = j9rtv_verifierGetRAMClass (verifyData, verifyData->classLoader, J9UTF8_DATA(currentClassName), J9UTF8_LENGTH(currentClassName), reasonCode);980if ((NULL == currentRamClass) && (BCV_ERR_INSUFFICIENT_MEMORY == *reasonCode)) {981return FALSE;982}983984/* short circuit - check currentRamClass hierarchy for member - if not found, protected access is permitted */985definingRamClass = currentRamClass;986if (isField) {987rc = findFieldFromRamClass(&definingRamClass, (J9ROMFieldRef *) member, FALSE);988} else {989rc = findMethodFromRamClass(verifyData, &definingRamClass, (J9ROMNameAndSignature *) member, FALSE);990}991992/* Return if member is not found if currentRamClass hierarchy - access okay */993if (BCV_NOT_FOUND == rc) return TRUE;994995/* Now chase the definition from the declaringClass */996definingRamClass = j9rtv_verifierGetRAMClass (verifyData, verifyData->classLoader, J9UTF8_DATA(declaringClassName), J9UTF8_LENGTH(declaringClassName), reasonCode);997if (NULL == definingRamClass) {998return FALSE;999}10001001/* Jazz 106868:1002* According to VM Spec at 4.10.1.8 Type Checking for protected Members,1003* the protected check applies only to protected members of superclasses of the current class1004* protected members in other classes will be caught by the access checking done at resolution.1005* So we ignore the protected checking since declaringClass is not the same or super class of currentClass.1006*/1007if (!isSameOrSuperClassOf (definingRamClass, currentRamClass)) {1008return TRUE;1009}10101011if (isField) {1012rc = findFieldFromRamClass(&definingRamClass, (J9ROMFieldRef *) member, TRUE);1013} else {1014rc = findMethodFromRamClass(verifyData, &definingRamClass, (J9ROMNameAndSignature *) member, TRUE);1015}10161017/* Return if the member is not protected or not found */1018if ((BCV_SUCCESS == rc) || (BCV_NOT_FOUND == rc)) {1019return TRUE;1020}10211022/* Check if in the same package */1023if (currentRamClass->packageID == definingRamClass->packageID) return TRUE;10241025/* Determine if the defining class is the same class or a super class of current class */1026if (isSameOrSuperClassOf(definingRamClass, currentRamClass)) {1027U_8 * targetClassName = NULL;1028UDATA targetClassLength = 0;1029J9Class * targetRamClass = NULL;10301031/* NULL is compatible */1032if (targetClass != BCV_BASE_TYPE_NULL) {1033/* Get the targetRamClass */1034getNameAndLengthFromClassNameList(verifyData, J9CLASS_INDEX_FROM_CLASS_ENTRY(targetClass), &targetClassName, &targetClassLength);1035targetRamClass = j9rtv_verifierGetRAMClass(verifyData, verifyData->classLoader, targetClassName, targetClassLength, reasonCode);1036if (NULL == targetRamClass) {1037return FALSE;1038}10391040/* Determine if the targetRamClass is the same class or a sub class of the current class */1041/* flipped logic - currentRamClass is the same class or a super class of the target class */1042if (J9ROMCLASS_IS_HIDDEN(romClass)) {1043currentClassName = J9ROMCLASS_CLASSNAME(romClass);1044if (!J9UTF8_DATA_EQUALS(targetClassName, targetClassLength, J9UTF8_DATA(currentClassName), J9UTF8_LENGTH(currentClassName))) {1045/* fail if current class and target class are not the same */1046return FALSE;1047}1048} else {1049if (!isSameOrSuperClassOf(currentRamClass, targetRamClass)) {1050/* fail */1051return FALSE;1052}1053}1054}1055}1056}1057return TRUE;1058}1059106010611062/* return TRUE if identical, FALSE otherwise */1063static UDATA compareTwoUTF8s(J9UTF8 * first, J9UTF8 * second)1064{1065return J9UTF8_EQUALS(first, second);1066}1067106810691070static void getNameAndLengthFromClassNameList (J9BytecodeVerificationData *verifyData, UDATA listIndex, U_8 ** name, UDATA * length)1071{1072U_32 * offset;10731074offset = (U_32 *) verifyData->classNameList[listIndex];1075*length = (U_32) J9UTF8_LENGTH(offset + 1);1076if (offset[0] == 0) {1077*name = J9UTF8_DATA(offset + 1);1078} else {1079J9ROMClass * romClass = verifyData->romClass;1080*name = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);1081}1082#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)1083if (IS_QTYPE(*(char *)*name)1084&& (';' == *(char *)(*name + (*length - 1)))1085) {1086/* we are dealing with signature envelope, extract the name from it */1087*name += 1;1088*length -= 2;1089}1090#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */1091}10921093/* return BCV_SUCCESS if field is found1094* return BCV_NOT_FOUND if field is not found1095* return BCV_FAIL otherwise1096*/10971098static IDATA findFieldFromRamClass (J9Class ** ramClass, J9ROMFieldRef * field, UDATA firstSearch)1099{1100J9UTF8 * searchName = J9ROMNAMEANDSIGNATURE_NAME(J9ROMFIELDREF_NAMEANDSIGNATURE(field));11011102for (;;) {1103J9ROMFieldShape * currentField;1104J9ROMClass * romClass = (*ramClass)->romClass;1105J9ROMFieldWalkState state;11061107/* Walk the instance fields looking for a match */1108currentField = romFieldsStartDo(romClass, &state);1109while (currentField != NULL) {1110if ((currentField->modifiers & J9AccStatic) == 0) {1111if (compareTwoUTF8s(searchName, J9ROMFIELDSHAPE_NAME(currentField))) {1112if (currentField->modifiers & CFR_ACC_PROTECTED) return BCV_FAIL;1113if (firstSearch) return BCV_SUCCESS;1114}1115}1116currentField = romFieldsNextDo(&state);1117}11181119/* Next try the super class */1120*ramClass = SUPERCLASS(*ramClass);1121if (NULL == *ramClass) return BCV_NOT_FOUND;1122}1123}11241125/* return BCV_SUCCESS if method is found1126* return BCV_NOT_FOUND if method is not found1127* return BCV_FAIL otherwise1128*/1129static IDATA1130findMethodFromRamClass(J9BytecodeVerificationData * verifyData, J9Class ** ramClass, J9ROMNameAndSignature * method, UDATA firstSearch)1131{1132J9UTF8 * searchName = J9ROMNAMEANDSIGNATURE_NAME(method);1133J9UTF8 * searchSignature = J9ROMNAMEANDSIGNATURE_SIGNATURE(method);11341135for (;;) {1136J9ROMClass * romClass = (*ramClass)->romClass;1137UDATA redefinedClassIndex = 0;1138J9UTF8 * currentClassName = J9ROMCLASS_CLASSNAME(romClass);1139J9ROMMethod * currentRomMethod = NULL;1140UDATA methodIndex = 0;11411142/* CMVC 193469: Walk through the redefined classes looking for a class name that1143* matches the current class name and use the new class instead */1144for (redefinedClassIndex = 0; redefinedClassIndex < verifyData->redefinedClassesCount; redefinedClassIndex++) {1145J9ROMClass * currentRedefinedClass = verifyData->redefinedClasses[redefinedClassIndex].replacementClass.romClass;1146Assert_RTV_true(NULL != currentRedefinedClass);11471148if (0 != compareTwoUTF8s(currentClassName, J9ROMCLASS_CLASSNAME(currentRedefinedClass))) {1149/* use the redefined class when checking the methods */1150romClass = currentRedefinedClass;1151break;1152}1153}11541155/* Walk the methods looking for a match */1156currentRomMethod = J9ROMCLASS_ROMMETHODS(romClass);1157for (methodIndex = 0; methodIndex < romClass->romMethodCount; methodIndex++) {1158if ((0 != compareTwoUTF8s(searchName, J9ROMMETHOD_NAME(currentRomMethod)))1159&& (0 != compareTwoUTF8s(searchSignature, J9ROMMETHOD_SIGNATURE(currentRomMethod)))1160) {1161if (currentRomMethod->modifiers & CFR_ACC_PROTECTED) return BCV_FAIL;1162if (firstSearch) return BCV_SUCCESS;1163}1164currentRomMethod = J9_NEXT_ROM_METHOD(currentRomMethod);1165}11661167/* Next try the super class */1168*ramClass = SUPERCLASS(*ramClass);1169if (NULL == *ramClass) return BCV_NOT_FOUND;1170}1171}11721173UDATA1174parseObjectOrArrayName(J9BytecodeVerificationData *verifyData, U_8 *signature)1175{1176UDATA arity, arrayType;1177U_8 *string = signature;11781179while (*signature == '[') {1180signature++;1181}1182arity = (UDATA) (signature - string);1183if (IS_REF_OR_VAL_SIGNATURE(*signature)) {1184U_16 length = 0;1185UDATA classIndex = 0;11861187signature++;1188string = signature; /* remember the start of the string */1189while (*signature++ != ';') {1190length++;1191}1192arrayType = convertClassNameToStackMapType(verifyData, string, length, 0, arity);11931194} else {1195/* Base arrays have implicit arity of 1 */1196arity--;1197arrayType = (UDATA) (BCV_TAG_BASE_ARRAY_OR_NULL + (UDATA) baseTypeCharConversion[*signature - 'A']);1198}11991200return arrayType | (arity << BCV_ARITY_SHIFT);1201}120212031204void1205storeVerifyErrorData (J9BytecodeVerificationData * verifyData, I_16 errorDetailCode, U_32 errorCurrentFramePosition, UDATA errorTargetType, UDATA errorTempData, IDATA currentPC)1206{1207J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;1208verifyData->errorDetailCode = errorDetailCode;1209verifyData->errorCurrentFramePosition = errorCurrentFramePosition;1210verifyData->errorTargetType = errorTargetType;1211verifyData->errorTempData = errorTempData;12121213/* Jazz 82615: Set liveStack->pc to the current pc value in the current frame (liveStack)1214* info of the detailed error message.1215*/1216liveStack->pc = (UDATA)currentPC;1217}121812191220