Path: blob/master/runtime/bcverify/staticverify.c
5986 views
/*******************************************************************************1* Copyright (c) 1991, 2022 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 <string.h>2324/* #include "bcvcfr.h" */2526#include "cfreader.h"27#include "bcsizes.h"28#include "j9protos.h"29#include "vrfyconvert.h"3031#include "ut_j9bcverify.h"3233#define BYTECODE_START 134#define STACKMAP_START 23536#define FATAL_CLASS_FORMAT_ERROR -137#define FALLBACK_CLASS_FORMAT_ERROR -238#define FALLBACK_VERIFY_ERROR -33940typedef struct StackmapExceptionDetails {41I_32 stackmapFrameIndex;42U_32 stackmapFrameBCI;43} StackmapExceptionDetails;4445static IDATA checkMethodStructure (J9PortLibrary * portLib, J9CfrClassFile * classfile, UDATA methodIndex, U_8 * instructionMap, J9CfrError * error, U_32 flags, I_32 *hasRET);46static IDATA buildInstructionMap (J9CfrClassFile * classfile, J9CfrAttributeCode * code, U_8 * map, UDATA methodIndex, J9CfrError * error);47static IDATA checkBytecodeStructure (J9CfrClassFile * classfile, UDATA methodIndex, UDATA length, U_8 * map, J9CfrError * error, U_32 flags, I_32 *hasRET);48static IDATA checkStackMap (J9CfrClassFile* classfile, J9CfrMethod * method, J9CfrAttributeCode * code, U_8 * map, UDATA flags, StackmapExceptionDetails* exceptionDetails);49static I_32 checkStackMapEntries (J9CfrClassFile* classfile, J9CfrAttributeCode * code, U_8 * map, U_8 ** entries, UDATA slotCount, U_8 * end, UDATA checkAppendArraySize);5051static IDATA52buildInstructionMap (J9CfrClassFile * classfile, J9CfrAttributeCode * code, U_8 * map, UDATA methodIndex, J9CfrError * error)53{54U_8 *bcStart;55U_8 *bcIndex;56U_8 *bcEnd;57UDATA bc, npairs, temp;58IDATA pc, high, low, tableSize;59U_16 errorType;6061bcStart = code->code;62bcIndex = bcStart;63bcEnd = bcIndex + (code->codeLength * sizeof(U_8));64pc = 0;65while (bcIndex < bcEnd) {66bc = (UDATA) *bcIndex;67pc = bcIndex - bcStart;68map[pc] = BYTECODE_START;69if (bc < CFR_BC_tableswitch) {70/* short circuit the switch for always clean ones */71bcIndex += (sunJavaByteCodeRelocation[bc] & 7);72continue;73}74switch (bc) {75case CFR_BC_wide:76if (*(bcIndex + 1) == CFR_BC_iinc) {77bcIndex += 6;78} else {79bcIndex += 4;80}81break;8283case CFR_BC_tableswitch:84bcIndex += (4 - (pc & 3));85bcIndex += 4;86low = (IDATA) NEXT_U32(temp, bcIndex);87high = (IDATA) NEXT_U32(temp, bcIndex);88tableSize = ((I_32)high - (I_32)low + 1);89if ((I_32)low > (I_32)high || tableSize <=0 || tableSize >= 16384){90errorType = J9NLS_CFR_ERR_BC_SWITCH_EMPTY__ID;91goto _leaveProc;92}93bcIndex += tableSize * 4;94/*95* If overflow occurred, bcIndex will be less than or equal to the bcIndex of the start of this bytecode.96* We need to check for this explicitly, as the (bcIndex < bcEnd) loop condition will not catch this case.97*/98if (bcIndex <= (bcStart + pc)) {99errorType = J9NLS_CFR_ERR_BC_INCOMPLETE__ID;100goto _leaveProc;101}102break;103104case CFR_BC_lookupswitch:105bcIndex += (4 - (pc & 3));106bcIndex += 4;107low = (IDATA) NEXT_U32(npairs, bcIndex);108if ((I_32)low < 0) {109errorType = J9NLS_CFR_ERR_BC_SWITCH_NEGATIVE_COUNT__ID;110goto _leaveProc;111}112bcIndex += npairs * 8;113/*114* If overflow occurred, bcIndex will be less than or equal to the bcIndex of the start of this bytecode.115* We need to check for this explicitly, as the (bcIndex < bcEnd) loop condition will not catch this case.116*/117if (bcIndex <= (bcStart + pc)) {118errorType = J9NLS_CFR_ERR_BC_INCOMPLETE__ID;119goto _leaveProc;120}121break;122123default:124if ((bc > CFR_BC_MaxDefined) || (bc == CFR_BC_breakpoint)) {125errorType = J9NLS_CFR_ERR_BC_UNKNOWN__ID;126goto _leaveProc;127}128bcIndex += (sunJavaByteCodeRelocation[bc] & 7);129}130}131132133return 0;134135_leaveProc:136Trc_STV_buildInstructionMap_VerifyError(errorType, methodIndex, pc);137buildMethodError(error, errorType, CFR_ThrowVerifyError, (I_32)methodIndex, (U_32)pc, &classfile->methods[methodIndex], classfile->constantPool);138return -1;139}140141142143/*144##class format checking145146Walk the sun bytecodes checking for illegal branch targets and doing some constant pool verification147148Invalid returns will cause us to modify the classfile in place such that the second pass of the verification can correctly149throw the error (unless it turns out to be dead code).150151*/152153static IDATA154checkBytecodeStructure (J9CfrClassFile * classfile, UDATA methodIndex, UDATA length, U_8 * map, J9CfrError * error, U_32 flags, I_32 *hasRET)155{156#define CHECK_END \157if(bcIndex > bcEnd) { \158errorType = J9NLS_CFR_ERR_BC_INCOMPLETE__ID; \159goto _verifyError; \160}161162J9CfrAttributeCode *code;163J9CfrConstantPoolInfo *info;164J9CfrMethod *method;165IDATA target, start, i1, i2, result, tableSize;166U_8 *bcStart, *bcInstructionStart, *bcIndex, *bcEnd;167UDATA bc, index, u1, u2, i, maxLocals, cpCount, tag;168UDATA sigChar;169UDATA errorType = 0;170UDATA errorDataIndex = 0;171172173method = &(classfile->methods[methodIndex]);174sigChar = (UDATA) getReturnTypeFromSignature(classfile->constantPool[method->descriptorIndex].bytes, classfile->constantPool[method->descriptorIndex].slot1, NULL);175code = method->codeAttribute;176177maxLocals = code->maxLocals;178cpCount = classfile->constantPoolCount;179180bcStart = code->code;181bcEnd = bcStart + length;182bcIndex = bcStart;183bcInstructionStart = bcIndex;184while (bcIndex < bcEnd) {185BOOLEAN noZeroIndex = FALSE;186bcInstructionStart = bcIndex;187/* Don't need to check that an instruction is in the code range here as method entries188have 4 extra bytes at the end - exception and attribute counts so we won't exceed189bcEnd by more than 4 (switches and wide iinc handled separately) and just test after the loop */190NEXT_U8(bc, bcIndex);191switch (bc) {192case CFR_BC_nop:193case CFR_BC_aconst_null:194case CFR_BC_iconst_m1:195case CFR_BC_iconst_0:196case CFR_BC_iconst_1:197case CFR_BC_iconst_2:198case CFR_BC_iconst_3:199case CFR_BC_iconst_4:200case CFR_BC_iconst_5:201case CFR_BC_lconst_0:202case CFR_BC_lconst_1:203case CFR_BC_fconst_0:204case CFR_BC_fconst_1:205case CFR_BC_fconst_2:206case CFR_BC_dconst_0:207case CFR_BC_dconst_1:208break;209210case CFR_BC_bipush:211bcIndex++;212break;213214case CFR_BC_sipush:215bcIndex+=2;216break;217218case CFR_BC_ldc:219case CFR_BC_ldc_w:220if (bc == CFR_BC_ldc) {221NEXT_U8(index, bcIndex);222} else {223NEXT_U16(index, bcIndex);224}225if ((!index) || (index >= cpCount)) {226errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;227/* Jazz 82615: Set the constant pool index to show up in the error message framework */228errorDataIndex = index;229goto _verifyError;230}231232info = &(classfile->constantPool[index]);233tag = (UDATA) info->tag;234{235switch (tag) {236case CFR_CONSTANT_Integer:237case CFR_CONSTANT_Float:238case CFR_CONSTANT_String:239break;240case CFR_CONSTANT_Class:241if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(5)) {242errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V49__ID;243errorDataIndex = index;244goto _verifyError;245}246break;247case CFR_CONSTANT_MethodType:248case CFR_CONSTANT_MethodHandle:249if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(7)) {250errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V51__ID;251errorDataIndex = index;252goto _verifyError;253}254break;255case CFR_CONSTANT_Dynamic:256{257J9CfrConstantPoolInfo *constantDynamicSignature = &classfile->constantPool[classfile->constantPool[info->slot2].slot2];258if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(11)) {259errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V55__ID;260errorDataIndex = index;261goto _verifyError;262} else if (('D' == constantDynamicSignature->bytes[0]) || ('J' == constantDynamicSignature->bytes[0])) {263errorType = J9NLS_CFR_ERR_BC_LDC_CONSTANT_DYNAMIC_RETURNS_LONG_OR_DOUBLE__ID;264errorDataIndex = index;265goto _verifyError;266}267}268break;269default:270errorType = J9NLS_CFR_ERR_BC_LDC_NOT_CONSTANT_OR_CONSTANT_DYNAMIC__ID;271errorDataIndex = index;272goto _verifyError;273}274}275break;276277case CFR_BC_ldc2_w:278279NEXT_U16(index, bcIndex);280/* Only check single slot index since Constant_Dynamic doesn't require double slots in the constant pool */281if ((!index) || (index >= cpCount)) {282errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;283/* Jazz 82615: Set the constant pool index to show up in the error message framework */284errorDataIndex = index;285goto _verifyError;286}287info = &(classfile->constantPool[index]);288tag = (UDATA) info->tag;289290if (CFR_CONSTANT_Dynamic == tag) {291J9CfrConstantPoolInfo *constantDynamicSignature = &classfile->constantPool[classfile->constantPool[info->slot2].slot2];292if ((flags & BCT_MajorClassFileVersionMask) < BCT_JavaMajorVersionShifted(11)) {293errorType = J9NLS_CFR_ERR_LDC_INDEX_INVALID_BEFORE_V55__ID;294errorDataIndex = index;295goto _verifyError;296} else if (('D' != constantDynamicSignature->bytes[0]) && ('J' != constantDynamicSignature->bytes[0])) {297errorType = J9NLS_CFR_ERR_BC_LDC2W_CONSTANT_DYNAMIC_NOT_LONG_OR_DOUBLE__ID;298errorDataIndex = index;299goto _verifyError;300}301} else if (index >= (cpCount - 1)) {302/* Not Constant_Dynamic entry, then must be a double slot constant,303* first check if second slot is valid before checking constant tag304*/305errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;306errorDataIndex = index;307goto _verifyError;308} else if ((CFR_CONSTANT_Double != tag) && (CFR_CONSTANT_Long != tag)) {309errorType = J9NLS_CFR_ERR_BC_LDC2W_NOT_CONSTANT_OR_CONSTANT_DYNAMIC__ID;310errorDataIndex = index;311goto _verifyError;312}313break;314315case CFR_BC_iload:316case CFR_BC_fload:317case CFR_BC_aload:318NEXT_U8(index, bcIndex);319320if (index >= maxLocals) {321errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;322/* Jazz 82615: Set the local variable index to show up in the error message framework */323errorDataIndex = index;324goto _verifyError;325}326break;327328case CFR_BC_lload:329case CFR_BC_dload:330NEXT_U8(index, bcIndex);331332if ((index + 1) >= maxLocals) {333errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;334/* Jazz 82615: Set the local variable index to show up in the error message framework */335errorDataIndex = index + 1;336goto _verifyError;337}338break;339340case CFR_BC_iload_0:341case CFR_BC_iload_1:342case CFR_BC_iload_2:343case CFR_BC_iload_3:344index = bc - CFR_BC_iload_0;345if (index >= maxLocals) {346errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;347/* Jazz 82615: Set the local variable index to show up in the error message framework */348errorDataIndex = index;349goto _verifyError;350}351break;352353case CFR_BC_lload_0:354case CFR_BC_lload_1:355case CFR_BC_lload_2:356case CFR_BC_lload_3:357index = bc - CFR_BC_lload_0;358if ((index + 1) >= maxLocals) {359errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;360/* Jazz 82615: Set the local variable index to show up in the error message framework */361errorDataIndex = index + 1;362goto _verifyError;363}364break;365366case CFR_BC_fload_0:367case CFR_BC_fload_1:368case CFR_BC_fload_2:369case CFR_BC_fload_3:370index = bc - CFR_BC_fload_0;371if (index >= maxLocals) {372errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;373/* Jazz 82615: Set the local variable index to show up in the error message framework */374errorDataIndex = index;375goto _verifyError;376}377break;378379case CFR_BC_dload_0:380case CFR_BC_dload_1:381case CFR_BC_dload_2:382case CFR_BC_dload_3:383index = bc - CFR_BC_dload_0;384if ((index + 1) >= maxLocals) {385errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;386/* Jazz 82615: Set the local variable index to show up in the error message framework */387errorDataIndex = index + 1;388goto _verifyError;389}390break;391392case CFR_BC_aload_0:393if (!maxLocals) {394errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;395/* Jazz 82615: Set the local variable index to show up in the error message framework */396errorDataIndex = 0;397goto _verifyError;398}399break;400401case CFR_BC_aload_1:402case CFR_BC_aload_2:403case CFR_BC_aload_3:404index = bc - CFR_BC_aload_0;405if (index >= maxLocals) {406errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;407/* Jazz 82615: Set the local variable index to show up in the error message framework */408errorDataIndex = index;409goto _verifyError;410}411break;412413case CFR_BC_iaload:414case CFR_BC_laload:415case CFR_BC_faload:416case CFR_BC_daload:417case CFR_BC_aaload:418case CFR_BC_baload:419case CFR_BC_caload:420case CFR_BC_saload:421break;422423case CFR_BC_istore:424case CFR_BC_fstore:425case CFR_BC_astore:426NEXT_U8(index, bcIndex);427428if (index >= maxLocals) {429errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;430/* Jazz 82615: Set the local variable index to show up in the error message framework */431errorDataIndex = index;432goto _verifyError;433}434break;435436case CFR_BC_lstore:437case CFR_BC_dstore:438NEXT_U8(index, bcIndex);439440if ((index + 1) >= maxLocals) {441errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;442/* Jazz 82615: Set the local variable index to show up in the error message framework */443errorDataIndex = index + 1;444goto _verifyError;445}446break;447448449case CFR_BC_istore_0:450case CFR_BC_istore_1:451case CFR_BC_istore_2:452case CFR_BC_istore_3:453index = bc - CFR_BC_istore_0;454if (index >= maxLocals) {455errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;456/* Jazz 82615: Set the local variable index to show up in the error message framework */457errorDataIndex = index;458goto _verifyError;459}460break;461462case CFR_BC_lstore_0:463case CFR_BC_lstore_1:464case CFR_BC_lstore_2:465case CFR_BC_lstore_3:466index = bc - CFR_BC_lstore_0;467if ((index + 1) >= maxLocals) {468errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;469/* Jazz 82615: Set the local variable index to show up in the error message framework */470errorDataIndex = index + 1;471goto _verifyError;472}473break;474475case CFR_BC_fstore_0:476case CFR_BC_fstore_1:477case CFR_BC_fstore_2:478case CFR_BC_fstore_3:479index = bc - CFR_BC_fstore_0;480if (index >= maxLocals) {481errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;482/* Jazz 82615: Set the local variable index to show up in the error message framework */483errorDataIndex = index;484goto _verifyError;485}486break;487488case CFR_BC_dstore_0:489case CFR_BC_dstore_1:490case CFR_BC_dstore_2:491case CFR_BC_dstore_3:492index = bc - CFR_BC_dstore_0;493if ((index + 1) >= maxLocals) {494errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;495/* Jazz 82615: Set the local variable index to show up in the error message framework */496errorDataIndex = index + 1;497goto _verifyError;498}499break;500501case CFR_BC_astore_0:502case CFR_BC_astore_1:503case CFR_BC_astore_2:504case CFR_BC_astore_3:505index = bc - CFR_BC_astore_0;506if (index >= maxLocals) {507errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;508/* Jazz 82615: Set the local variable index to show up in the error message framework */509errorDataIndex = index;510goto _verifyError;511}512break;513514case CFR_BC_iastore:515case CFR_BC_lastore:516case CFR_BC_fastore:517case CFR_BC_dastore:518case CFR_BC_aastore:519case CFR_BC_bastore:520case CFR_BC_castore:521case CFR_BC_sastore:522break;523524case CFR_BC_pop:525case CFR_BC_pop2:526case CFR_BC_dup:527case CFR_BC_dup_x1:528case CFR_BC_dup_x2:529case CFR_BC_dup2:530case CFR_BC_dup2_x1:531case CFR_BC_dup2_x2:532case CFR_BC_swap:533break;534535case CFR_BC_iadd:536case CFR_BC_ladd:537case CFR_BC_fadd:538case CFR_BC_dadd:539case CFR_BC_isub:540case CFR_BC_lsub:541case CFR_BC_fsub:542case CFR_BC_dsub:543case CFR_BC_imul:544case CFR_BC_lmul:545case CFR_BC_fmul:546case CFR_BC_dmul:547case CFR_BC_idiv:548case CFR_BC_ldiv:549case CFR_BC_fdiv:550case CFR_BC_ddiv:551case CFR_BC_irem:552case CFR_BC_lrem:553case CFR_BC_frem:554case CFR_BC_drem:555case CFR_BC_ineg:556case CFR_BC_lneg:557case CFR_BC_fneg:558case CFR_BC_dneg:559case CFR_BC_ishl:560case CFR_BC_lshl:561case CFR_BC_ishr:562case CFR_BC_lshr:563case CFR_BC_iushr:564case CFR_BC_lushr:565case CFR_BC_iand:566case CFR_BC_land:567case CFR_BC_ior:568case CFR_BC_lor:569case CFR_BC_ixor:570case CFR_BC_lxor:571break;572573case CFR_BC_iinc:574NEXT_U8(u1, bcIndex);575bcIndex++;576if (u1 >= maxLocals) {577errorType = J9NLS_CFR_ERR_BC_IINC_INDEX__ID;578/* Jazz 82615: Set the local variable index to show up in the error message framework */579errorDataIndex = u1;580goto _verifyError;581}582break;583584case CFR_BC_i2l:585case CFR_BC_i2f:586case CFR_BC_i2d:587case CFR_BC_l2i:588case CFR_BC_l2f:589case CFR_BC_l2d:590case CFR_BC_f2i:591case CFR_BC_f2l:592case CFR_BC_f2d:593case CFR_BC_d2i:594case CFR_BC_d2l:595case CFR_BC_d2f:596case CFR_BC_i2b:597case CFR_BC_i2c:598case CFR_BC_i2s:599break;600601case CFR_BC_lcmp:602case CFR_BC_fcmpl:603case CFR_BC_fcmpg:604case CFR_BC_dcmpl:605case CFR_BC_dcmpg:606break;607608case CFR_BC_jsr:609method->j9Flags |= CFR_J9FLAG_HAS_JSR;610classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;611noZeroIndex = TRUE;612613/* fall through */614615case CFR_BC_goto:616case CFR_BC_ifeq:617case CFR_BC_ifne:618case CFR_BC_iflt:619case CFR_BC_ifge:620case CFR_BC_ifgt:621case CFR_BC_ifle:622case CFR_BC_if_icmpeq:623case CFR_BC_if_icmpne:624case CFR_BC_if_icmplt:625case CFR_BC_if_icmpge:626case CFR_BC_if_icmpgt:627case CFR_BC_if_icmple:628case CFR_BC_if_acmpeq:629case CFR_BC_if_acmpne:630case CFR_BC_ifnull:631case CFR_BC_ifnonnull:632start = bcIndex - bcStart - 1;633NEXT_U16(index, bcIndex);634target = (I_16) index + start;635if ((U_32) target >= (U_32) length) {636errorType = J9NLS_CFR_ERR_BC_JUMP_OFFSET__ID;637goto _verifyError;638}639if (!map[target]) {640errorType = J9NLS_CFR_ERR_BC_JUMP_TARGET__ID;641goto _verifyError;642}643if (noZeroIndex && (0 == index)) {644errorType = J9NLS_CFR_ERR_BC_JUMP_RECURSIVE__ID;645goto _verifyError;646}647break;648649case CFR_BC_ret:650*hasRET = 1;651method->j9Flags |= CFR_J9FLAG_HAS_JSR;652classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;653NEXT_U8(index, bcIndex);654if (index >= maxLocals) {655errorType = J9NLS_CFR_ERR_BC_RET_INDEX__ID;656goto _verifyError;657}658break;659660case CFR_BC_tableswitch:661start = bcIndex - bcStart - 1;662i1 = 3 - (start & 3);663bcIndex += i1;664CHECK_END;665bcIndex -= i1;666for (i2 = 0; i2 < i1; i2++) {667NEXT_U8(index, bcIndex);668if ((0 != index)669&& (flags & CFR_Xfuture)670&& (classfile->majorVersion < CFR_MAJOR_VERSION_REQUIRING_STACKMAPS)671) {672errorType = J9NLS_CFR_ERR_BC_SWITCH_PAD__ID;673goto _verifyError;674}675}676677bcIndex += 12;678CHECK_END;679bcIndex -= 12;680NEXT_U32(u1, bcIndex);681target = start + (I_32) u1;682if ((UDATA) target >= length) {683errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;684goto _verifyError;685}686if (!map[target]) {687errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;688goto _verifyError;689}690i1 = (I_32) NEXT_U32(u1, bcIndex);691i2 = (I_32) NEXT_U32(u2, bcIndex);692tableSize = i2 - i1 + 1;693if (i1 > i2 || tableSize <= 0 || tableSize >= 16384) {694errorType = J9NLS_CFR_ERR_BC_SWITCH_EMPTY__ID;695goto _verifyError;696}697698bcIndex += tableSize * 4;699CHECK_END;700bcIndex -= tableSize * 4;701702/* Count the entries */703i2 = tableSize;704for (i1 = 0; i1 < i2; i1++) {705NEXT_U32(u1, bcIndex);706target = start + (I_32) u1;707if ((UDATA) target >= length) {708errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;709goto _verifyError;710}711if (!map[target]) {712errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;713goto _verifyError;714}715}716break;717718case CFR_BC_lookupswitch:719start = bcIndex - bcStart - 1;720i1 = 3 - (start & 3);721bcIndex += i1;722CHECK_END;723bcIndex -= i1;724for (i2 = 0; i2 < i1; i2++) {725NEXT_U8(index, bcIndex);726if ((0 != index)727&& (flags & CFR_Xfuture)728&& (classfile->majorVersion < CFR_MAJOR_VERSION_REQUIRING_STACKMAPS)729) {730errorType = J9NLS_CFR_ERR_BC_SWITCH_PAD__ID;731goto _verifyError;732}733}734735bcIndex += 8;736CHECK_END;737bcIndex -= 8;738NEXT_U32(u1, bcIndex);739target = start + (I_32) u1;740if ((UDATA) target >= length) {741errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;742goto _verifyError;743}744if (!map[target]) {745errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;746goto _verifyError;747}748NEXT_U32(u1, bcIndex);749750bcIndex += (I_32) u1 * 8;751CHECK_END;752bcIndex -= (I_32) u1 * 8;753754for (i = 0; i < u1; i++) {755/* Skip over match/key part of match-offset pair. Match/key order is verified in the second verification pass */756NEXT_U32(u2, bcIndex);757758target = start + (I_32) NEXT_U32(u2, bcIndex);759if ((UDATA) target >= length) {760errorType = J9NLS_CFR_ERR_BC_SWITCH_OFFSET__ID;761goto _verifyError;762}763if (!map[target]) {764errorType = J9NLS_CFR_ERR_BC_SWITCH_TARGET__ID;765goto _verifyError;766}767}768break;769770case CFR_BC_ireturn:771switch (sigChar) {772case 'B':773case 'C':774case 'I':775case 'S':776case 'Z':777break;778default:779/* fail, modify the bytecode to be incompatible in the second pass of verification */780if (sigChar != 'V') {781*(bcIndex - 1) = CFR_BC_return;782}783}784break;785786case CFR_BC_lreturn:787if (sigChar != 'J') {788/* fail, modify the bytecode to be incompatible in the second pass of verification */789if (sigChar != 'V') {790*(bcIndex - 1) = CFR_BC_return;791}792}793break;794795case CFR_BC_freturn:796if (sigChar != 'F') {797/* fail, modify the bytecode to be incompatible in the second pass of verification */798if (sigChar != 'V') {799*(bcIndex - 1) = CFR_BC_return;800}801}802break;803804case CFR_BC_dreturn:805if (sigChar != 'D') {806/* fail, modify the bytecode to be incompatible in the second pass of verification */807if (sigChar != 'V') {808*(bcIndex - 1) = CFR_BC_return;809}810}811break;812813case CFR_BC_areturn:814if (!IS_REF_OR_VAL_SIGNATURE(sigChar) && (sigChar != '[')) {815/* fail, modify the bytecode to be incompatible in the second pass of verification */816if (sigChar != 'V') {817*(bcIndex - 1) = CFR_BC_return;818}819}820break;821822case CFR_BC_return:823/* do not modify the bytecode at all, if the return matches we're good, if it does not match it will fail as expected824if (sigChar != 'V') {825fail, modify the bytecode to be incompatible in the second pass of verification826*(bcIndex - 1) = CFR_BC_return; leaving it alone will cause this to fail827}828*/829break;830831#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)832case CFR_BC_withfield:833#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */834case CFR_BC_getstatic:835case CFR_BC_putstatic:836case CFR_BC_getfield:837case CFR_BC_putfield:838NEXT_U16(index, bcIndex);839if ((!index) || (index >= cpCount)) {840errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;841/* Jazz 82615: Set the constant pool index to show up in the error message framework */842errorDataIndex = index;843goto _verifyError;844}845info = &(classfile->constantPool[index]);846if (info->tag != CFR_CONSTANT_Fieldref) {847errorType = J9NLS_CFR_ERR_BC_NOT_FIELDREF__ID;848/* Jazz 82615: Set the constant pool index to show up in the error message framework */849errorDataIndex = index;850goto _verifyError;851}852/* field signature has been already been checked by j9bcv_verifyClassStructure() */853break;854855case CFR_BC_invokespecial:856case CFR_BC_invokevirtual:857case CFR_BC_invokestatic:858/* Implicitly includes invokehandle & invokehandlegeneric bytecodes859* as they haven't been split from invokevirtual yet */860NEXT_U16(index, bcIndex);861if ((!index) || (index >= cpCount)) {862errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;863/* Jazz 82615: Set the constant pool index to show up in the error message framework */864errorDataIndex = index;865goto _verifyError;866}867info = &(classfile->constantPool[index]);868if (info->tag != CFR_CONSTANT_Methodref) {869BOOLEAN isJava8orLater = ((flags & BCT_MajorClassFileVersionMask) >= BCT_JavaMajorVersionShifted(8)) || J9_ARE_ANY_BITS_SET(flags, BCT_Unsafe);870871if (isJava8orLater && (bc != CFR_BC_invokevirtual) && (info->tag == CFR_CONSTANT_InterfaceMethodref)) {872/* JVMS 4.9.1 Static Constraints:873* The indexbyte operands of each invokespecial and invokestatic instruction must represent874* a valid index into the constant_pool table. The constant pool entry referenced by that875* index must be either of type CONSTANT_Methodref or of type CONSTANT_InterfaceMethodref.876*/877/* Valid - take no action */878} else {879errorType = J9NLS_CFR_ERR_BC_NOT_METHODREF__ID;880/* Jazz 82615: Set the constant pool index to show up in the error message framework */881errorDataIndex = index;882goto _verifyError;883}884}885index = info->slot2;886info = &(classfile->constantPool[classfile->constantPool[index].slot1]);887U_16 returnChar = getReturnTypeFromSignature(classfile->constantPool[classfile->constantPool[index].slot2].bytes, classfile->constantPool[classfile->constantPool[index].slot2].slot1, NULL);888if (info->bytes[0] == '<') {889if ((IS_QTYPE(returnChar) && (bc != CFR_BC_invokestatic))890|| (!IS_QTYPE(returnChar) && (bc != CFR_BC_invokespecial))891|| (info->tag != CFR_CONSTANT_Utf8)892|| !J9UTF8_DATA_EQUALS("<init>", 6, info->bytes, info->slot1)893) {894errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID__ID;895goto _verifyError;896}897}898/* Check for '<init> returns V' already done in j9bcv_verifyClassStructure */899/* Check for 'argCount <= 255' already done in j9bcv_verifyClassStructure */900break;901902case CFR_BC_invokeinterface:903{904IDATA argCount = 0;905906NEXT_U16(index, bcIndex);907if ((!index) || (index >= cpCount)) {908errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;909/* Jazz 82615: Set the constant pool index to show up in the error message framework */910errorDataIndex = index;911goto _verifyError;912}913info = &(classfile->constantPool[index]);914if (info->tag != CFR_CONSTANT_InterfaceMethodref) {915errorType = J9NLS_CFR_ERR_BC_NOT_INTERFACEMETHODREF__ID;916/* Jazz 82615: Set the constant pool index to show up in the error message framework */917errorDataIndex = index;918goto _verifyError;919}920info = &(classfile->constantPool[info->slot2]);921if (classfile->constantPool[info->slot1].bytes[0] == '<') {922errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID__ID;923goto _verifyError;924}925NEXT_U8(index, bcIndex);926if ((argCount = j9bcv_checkMethodSignature(&(classfile->constantPool[info->slot2]), TRUE)) == -1) {927errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;928goto _verifyError;929}930/* Check for 'argCount <= 255' when checking CFR_CONSTANT_*Methodref */931if (argCount != ((IDATA) index - 1)) {932errorType = J9NLS_CFR_ERR_BC_METHOD_NARGS__ID;933goto _verifyError;934}935NEXT_U8(index, bcIndex);936if (index) {937errorType = J9NLS_CFR_ERR_BC_METHOD_RESERVED__ID;938goto _verifyError;939}940break;941}942943case CFR_BC_invokedynamic:944NEXT_U16(index, bcIndex);945if ((0 == index) || (index >= cpCount)) {946errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;947/* Jazz 82615: Set the constant pool index to show up in the error message framework */948errorDataIndex = index;949goto _verifyError;950}951info = &(classfile->constantPool[index]);952if (info->tag != CFR_CONSTANT_InvokeDynamic) {953errorType = J9NLS_CFR_ERR_BC_NOT_INVOKEDYNAMIC__ID;954/* Jazz 82615: Set the constant pool index to show up in the error message framework */955errorDataIndex = index;956goto _verifyError;957}958info = &(classfile->constantPool[info->slot2]);959if (classfile->constantPool[info->slot1].bytes[0] == '<') {960errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID__ID;961goto _verifyError;962}963/* TODO what other verification is required? */964NEXT_U16(index, bcIndex);965if (0 != index) {966errorType = J9NLS_CFR_ERR_BC_INVOKEDYNAMIC_RESERVED__ID;967goto _verifyError;968}969break;970971#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)972case CFR_BC_aconst_init:973/* fall through */974#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */975case CFR_BC_new:976NEXT_U16(index, bcIndex);977if ((!index) || (index >= cpCount)) {978errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;979/* Jazz 82615: Set the constant pool index to show up in the error message framework */980errorDataIndex = index;981goto _verifyError;982}983info = &(classfile->constantPool[index]);984if (info->tag != CFR_CONSTANT_Class) {985errorType = J9NLS_CFR_ERR_BC_NEW_NOT_CLASS__ID;986/* Jazz 82615: Set the constant pool index to show up in the error message framework */987errorDataIndex = index;988goto _verifyError;989}990break;991992case CFR_BC_newarray:993NEXT_U8(index, bcIndex);994if ((index < 4) || (index > 11)) {995errorType = J9NLS_CFR_ERR_BC_NEWARRAY_TYPE__ID;996goto _verifyError;997}998break;9991000case CFR_BC_anewarray:1001NEXT_U16(index, bcIndex);1002if ((!index) || (index >= cpCount)) {1003errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;1004/* Jazz 82615: Set the constant pool index to show up in the error message framework */1005errorDataIndex = index;1006goto _verifyError;1007}1008info = &(classfile->constantPool[index]);1009if (info->tag != CFR_CONSTANT_Class) {1010errorType = J9NLS_CFR_ERR_BC_ANEWARRAY_NOT_CLASS__ID;1011/* Jazz 82615: Set the constant pool index to show up in the error message framework */1012errorDataIndex = index;1013goto _verifyError;1014}1015break;10161017case CFR_BC_arraylength:1018break;10191020case CFR_BC_athrow:1021break;10221023case CFR_BC_checkcast:1024NEXT_U16(index, bcIndex);1025if ((!index) || (index >= cpCount)) {1026errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;1027/* Jazz 82615: Set the constant pool index to show up in the error message framework */1028errorDataIndex = index;1029goto _verifyError;1030}1031info = &(classfile->constantPool[index]);1032if (info->tag != CFR_CONSTANT_Class) {1033errorType = J9NLS_CFR_ERR_BC_CHECKCAST_NOT_CLASS__ID;1034/* Jazz 82615: Set the constant pool index to show up in the error message framework */1035errorDataIndex = index;1036goto _verifyError;1037}1038break;10391040case CFR_BC_instanceof:1041NEXT_U16(index, bcIndex);1042if ((!index) || (index >= cpCount)) {1043errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;1044/* Jazz 82615: Set the constant pool index to show up in the error message framework */1045errorDataIndex = index;1046goto _verifyError;1047}1048info = &(classfile->constantPool[index]);1049if (info->tag != CFR_CONSTANT_Class) {1050errorType = J9NLS_CFR_ERR_BC_INSTANCEOF_NOT_CLASS__ID;1051/* Jazz 82615: Set the constant pool index to show up in the error message framework */1052errorDataIndex = index;1053goto _verifyError;1054}1055break;10561057case CFR_BC_monitorenter:1058case CFR_BC_monitorexit:1059break;10601061case CFR_BC_wide:1062NEXT_U8(bc, bcIndex);1063switch (bc) {10641065case CFR_BC_iload:1066case CFR_BC_fload:1067case CFR_BC_aload:1068NEXT_U16(index, bcIndex);10691070if (index >= maxLocals) {1071errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;1072/* Jazz 82615: Set the local variable index to show up in the error message framework */1073errorDataIndex = index;1074goto _verifyError;1075}1076break;10771078case CFR_BC_lload:1079case CFR_BC_dload:1080NEXT_U16(index, bcIndex);10811082if ((index + 1) >= maxLocals) {1083errorType = J9NLS_CFR_ERR_BC_LOAD_INDEX__ID;1084/* Jazz 82615: Set the local variable index to show up in the error message framework */1085errorDataIndex = index + 1;1086goto _verifyError;1087}1088break;10891090case CFR_BC_istore:1091case CFR_BC_fstore:1092case CFR_BC_astore:1093NEXT_U16(index, bcIndex);10941095if (index >= maxLocals) {1096errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;1097/* Jazz 82615: Set the local variable index to show up in the error message framework */1098errorDataIndex = index;1099goto _verifyError;1100}1101break;11021103case CFR_BC_lstore:1104case CFR_BC_dstore:1105NEXT_U16(index, bcIndex);11061107if ((index + 1) >= maxLocals) {1108errorType = J9NLS_CFR_ERR_BC_STORE_INDEX__ID;1109/* Jazz 82615: Set the local variable index to show up in the error message framework */1110errorDataIndex = index + 1;1111goto _verifyError;1112}1113break;11141115case CFR_BC_iinc:1116CHECK_END;1117NEXT_U16(u1, bcIndex);1118bcIndex+=2;1119if (u1 >= maxLocals) {1120errorType = J9NLS_CFR_ERR_BC_IINC_INDEX__ID;1121goto _verifyError;1122}1123break;11241125case CFR_BC_ret:1126*hasRET = 1;1127method->j9Flags |= CFR_J9FLAG_HAS_JSR;1128classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;1129NEXT_U16(index, bcIndex);1130if (index >= maxLocals) {1131errorType = J9NLS_CFR_ERR_BC_RET_INDEX__ID;1132goto _verifyError;1133}1134break;11351136default:1137errorType = J9NLS_CFR_ERR_BC_NOT_WIDE__ID;1138goto _verifyError;1139}1140break;11411142case CFR_BC_multianewarray:1143NEXT_U16(index, bcIndex);1144NEXT_U8(u1, bcIndex);1145if ((!index) || (index >= cpCount)) {1146errorType = J9NLS_CFR_ERR_BAD_INDEX__ID;1147/* Jazz 82615: Set the constant pool index to show up in the error message framework */1148errorDataIndex = index;1149goto _verifyError;1150}1151info = &(classfile->constantPool[index]);1152if (info->tag != CFR_CONSTANT_Class) {1153errorType = J9NLS_CFR_ERR_BC_MULTI_NOT_CLASS__ID;1154/* Jazz 82615: Set the constant pool index to show up in the error message framework */1155errorDataIndex = index;1156goto _verifyError;1157}1158info = &(classfile->constantPool[info->slot1]);1159u2 = 0;1160while (info->bytes[u2] == '[')1161u2++;1162if (!u2) {1163errorType = J9NLS_CFR_ERR_BC_MULTI_NOT_ARRAY__ID;1164goto _verifyError;1165}1166if ((!u1) || (u1 > u2)) {1167errorType = J9NLS_CFR_ERR_BC_MULTI_DIMS__ID;1168goto _verifyError;1169}1170break;11711172case CFR_BC_jsr_w:1173method->j9Flags |= CFR_J9FLAG_HAS_JSR;1174classfile->j9Flags |= CFR_J9FLAG_HAS_JSR;1175noZeroIndex = TRUE;11761177/* fall through */11781179case CFR_BC_goto_w:1180start = bcIndex - bcStart - 1;1181NEXT_U32(index, bcIndex);1182target = (I_32) index + start;1183if ((UDATA) target >= length) {1184errorType = J9NLS_CFR_ERR_BC_JUMP_OFFSET__ID;1185goto _verifyError;1186}1187if (!map[target]) {1188errorType = J9NLS_CFR_ERR_BC_JUMP_TARGET__ID;1189goto _verifyError;1190}1191if (noZeroIndex && (0 == index)) {1192errorType = J9NLS_CFR_ERR_BC_JUMP_RECURSIVE__ID;1193goto _verifyError;1194}1195break;11961197default:1198errorType = J9NLS_CFR_ERR_BC_UNKNOWN__ID;1199goto _verifyError;1200}1201}12021203CHECK_END;12041205result = 0;1206goto _leaveProc; /* All is well */12071208_verifyError:1209start = bcInstructionStart - bcStart;1210Trc_STV_checkBytecodeStructure_VerifyError(errorType, methodIndex, start);1211buildMethodErrorWithExceptionDetails(error,1212errorType,12130,1214CFR_ThrowVerifyError,1215(I_32)methodIndex,1216(U_32)start,1217method,1218classfile->constantPool,1219(U_32)errorDataIndex,1220-1,12210);1222result = -1;12231224_leaveProc:1225return result;12261227#undef CHECK_END1228}1229123012311232/**1233* Check whether any verification error occurs when walking through the stack map1234* @param classfile - pointer to J9CfrClassFile1235* @param method - pointer to J9CfrMethod1236* @param code - pointer to J9CfrAttributeCode1237* @param map - pointer to the stack map of the specified method1238* @param flags - settings in verification1239* @param exceptionDetails - pointer to StackmapExceptionDetails1240* @return 0 on success; otherwise, return a specific error code.1241*/1242static IDATA1243checkStackMap (J9CfrClassFile* classfile, J9CfrMethod * method, J9CfrAttributeCode * code, U_8 * map, UDATA flags, StackmapExceptionDetails* exceptionDetails)1244{1245UDATA i;1246IDATA errorCode = 0;1247J9CfrAttribute* attribute;12481249for (i = 0; i < code->attributesCount; i++) {1250attribute = code->attributes[i];12511252if (attribute->tag == CFR_ATTRIBUTE_StackMapTable){1253J9CfrAttributeStackMap * stackMap = (J9CfrAttributeStackMap *) attribute;1254U_8* entries = stackMap->entries;1255UDATA length = (UDATA) stackMap->mapLength;1256U_8* end = entries + length;1257UDATA j = 0;1258UDATA offset = (UDATA) -1;1259J9CfrConstantPoolInfo* info = &classfile->constantPool[method->descriptorIndex];12601261for (j = 0; j < stackMap->numberOfEntries; j++) {1262U_8 frameType;1263UDATA delta;1264IDATA slotCount;1265UDATA checkAppendArraySize = FALSE;12661267if ((entries + 1) > end) {1268errorCode = FATAL_CLASS_FORMAT_ERROR;1269goto _failedCheck;1270}1271frameType = *entries++;12721273if (frameType < CFR_STACKMAP_SAME_LOCALS_1_STACK) {1274offset += (UDATA) frameType;1275} else if (frameType < CFR_STACKMAP_SAME_LOCALS_1_STACK_END) {1276offset += (UDATA) frameType - (UDATA) CFR_STACKMAP_SAME_LOCALS_1_STACK;1277} else if (frameType >= CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED) {1278if ((entries + 2) > end) {1279errorCode = FATAL_CLASS_FORMAT_ERROR;1280goto _failedCheck;1281}1282offset += NEXT_U16(delta, entries); /* move past delta */1283} else {1284/* illegal frame type */1285errorCode = FATAL_CLASS_FORMAT_ERROR;1286goto _failedCheck;1287}1288offset++;12891290/* Throw the VerifyError without delay in the case of bad offset so as to match the RI's behavior */1291if ((offset >= code->codeLength) || (0 == map[offset])) {1292errorCode = FALLBACK_VERIFY_ERROR;1293exceptionDetails->stackmapFrameIndex = (I_32)j;1294exceptionDetails->stackmapFrameBCI = (U_32)offset;1295goto _failedCheck;1296}12971298if (entries > end) {1299errorCode = FATAL_CLASS_FORMAT_ERROR;1300goto _failedCheck;1301}13021303if (frameType != CFR_STACKMAP_FULL) {1304/* Only executed with StackMapTable */1305slotCount = 0;1306if ((frameType >= CFR_STACKMAP_SAME_LOCALS_1_STACK) && (frameType <= CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED)) {1307slotCount = 1;13081309/* The stackmap entry is invalid if the size of stack (1 slot) exceeds the size of the max stack.*/1310if (code->maxStack < slotCount) {1311errorCode = FATAL_CLASS_FORMAT_ERROR;1312goto _failedCheck;1313}1314}1315if (frameType >= CFR_STACKMAP_CHOP_3) {1316slotCount = (IDATA) frameType - CFR_STACKMAP_APPEND_BASE;1317if (slotCount < 0) {1318slotCount = 0;1319}13201321if ((frameType >= CFR_STACKMAP_APPEND_1) && (frameType <= CFR_STACKMAP_APPEND_3)) {1322checkAppendArraySize = TRUE;1323}1324}1325} else {1326/* full frame */1327/* Executed with StackMap or StackMapTable */1328NEXT_U16(slotCount, entries); /* number_of_locals verified in checkStackMapEntries */1329errorCode = checkStackMapEntries (classfile, code, map, &entries, slotCount, end, checkAppendArraySize);1330if (0 != errorCode) {1331goto _failedCheck;1332}1333NEXT_U16(slotCount, entries); /* number_of_stack_items verified in checkStackMapEntries */1334}1335errorCode = checkStackMapEntries (classfile, code, map, &entries, slotCount, end, checkAppendArraySize);1336if (0 != errorCode) {1337goto _failedCheck;1338}1339}13401341if (entries != end) {1342/* extra bytes in the attribute */1343errorCode = FATAL_CLASS_FORMAT_ERROR;1344goto _failedCheck;1345}1346}1347}1348_failedCheck:1349if ((FALLBACK_CLASS_FORMAT_ERROR == errorCode)1350|| (FALLBACK_VERIFY_ERROR == errorCode)1351) {1352if ((classfile->majorVersion < CFR_MAJOR_VERSION_REQUIRING_STACKMAPS)1353&& (0 == (flags & J9_VERIFY_NO_FALLBACK))1354) {1355/* Hide the bad StackMap/StackMapTable attribute and error. Major version 51 and greater do not allow fallback to type inference */1356attribute->tag = CFR_ATTRIBUTE_Unknown;1357errorCode = 0;1358}1359}13601361return errorCode;1362}1363136413651366static I_321367checkStackMapEntries (J9CfrClassFile* classfile, J9CfrAttributeCode * code, U_8 * map, U_8 ** entries, UDATA slotCount, U_8 * end, UDATA checkAppendArraySize)1368{1369U_8* entry = *entries;1370U_8 entryType;1371U_16 offset;1372U_16 cpIndex;1373J9CfrConstantPoolInfo* cpBase = classfile->constantPool;1374U_32 cpCount = (U_32) classfile->constantPoolCount;1375/* append check */1376U_16 slotTypeCounter = 0;1377UDATA hasDoubleSlot = FALSE;13781379for (; slotCount; slotCount--) {1380if ((entry + 1) > end) {1381return FATAL_CLASS_FORMAT_ERROR;1382}1383entryType = *entry++;13841385if (entry > end) {1386return FATAL_CLASS_FORMAT_ERROR;1387}13881389if (entryType > CFR_STACKMAP_TYPE_NEW_OBJECT) {1390/* Unknown entry */1391return FATAL_CLASS_FORMAT_ERROR;1392}13931394if (entryType == CFR_STACKMAP_TYPE_NEW_OBJECT) {1395if ((entry + 2) > end) {1396return FATAL_CLASS_FORMAT_ERROR;1397}1398NEXT_U16(offset, entry);13991400if (offset >= code->codeLength) {1401return FALLBACK_CLASS_FORMAT_ERROR;1402}14031404if (map[offset] == 0) {1405/* invalid bytecode index */1406return FALLBACK_CLASS_FORMAT_ERROR;1407}14081409if (code->code[offset] != CFR_BC_new) {1410return FALLBACK_CLASS_FORMAT_ERROR;1411}14121413} else if (entryType == CFR_STACKMAP_TYPE_OBJECT) {1414if ((entry + 2) > end) {1415return FATAL_CLASS_FORMAT_ERROR;1416}1417NEXT_U16(cpIndex, entry);1418/* Check index is in range */1419if ((!cpIndex) || (cpIndex > cpCount)) {1420return FATAL_CLASS_FORMAT_ERROR;1421}1422/* Check index points to the right type of thing */1423if(cpBase[cpIndex].tag != CFR_CONSTANT_Class) {1424return FATAL_CLASS_FORMAT_ERROR;1425}1426}14271428/* A value of type long or double must occupy two consecutive local variables. Ensure that if there is a long or double entry in1429* an append frame maxLocals reflects the correct number of slots. An incorrect maxLocals value in all other cases will be handled1430* in bcverify.c */1431if (checkAppendArraySize) {1432slotTypeCounter += 1;1433if ((CFR_STACKMAP_TYPE_DOUBLE == entryType) || (CFR_STACKMAP_TYPE_LONG == entryType)) {1434hasDoubleSlot = TRUE;1435slotTypeCounter += 1;1436}1437if (hasDoubleSlot && (slotTypeCounter > code->maxLocals)) {1438return FATAL_CLASS_FORMAT_ERROR;1439}1440}1441}14421443*entries = entry;1444return 0;1445}144614471448/*1449##class format checking14501451Check the Method provided and determine the1452referenced constant pool entries.14531454@results is an array of size classfile->constantPoolCount.1455@instructionMap is a handle to a pointer. If non-null, an instruction1456map will be created at this location.14571458Returns 0 on success, -1 on structure problem (error set), -2 on out of memory.14591460*/14611462static IDATA1463checkMethodStructure (J9PortLibrary * portLib, J9CfrClassFile * classfile, UDATA methodIndex, U_8 * instructionMap, J9CfrError * error, U_32 flags, I_32 *hasRET)1464{1465J9CfrAttributeCode *code;1466J9CfrMethod *method;1467J9CfrConstantPoolInfo * info;1468U_8 *map = NULL;1469UDATA i;1470IDATA result;1471UDATA length, pc = 0;1472U_16 errorType;14731474PORT_ACCESS_FROM_PORT (portLib);14751476method = &(classfile->methods[methodIndex]);1477code = method->codeAttribute;1478if (!code) {1479if ((method->accessFlags & CFR_ACC_NATIVE) || (method->accessFlags & CFR_ACC_ABSTRACT)) {1480result = 0;1481goto _leaveProc;1482} else {1483errorType = J9NLS_CFR_ERR_CODE_MISSING__ID;1484goto _formatError;1485}1486}14871488length = code->codeLength;1489if (length == 0) {1490errorType = J9NLS_CFR_ERR_CODE_ARRAY_EMPTY__ID;1491goto _formatError;1492}14931494if (instructionMap) {1495map = instructionMap;1496} else {1497map = j9mem_allocate_memory(length, J9MEM_CATEGORY_CLASSES);1498if (map == NULL) {1499result = -2;1500goto _leaveProc;1501}1502}1503memset (map, 0, length);15041505if (buildInstructionMap (classfile, code, map, methodIndex, error)) {1506result = -1;1507goto _leaveProc;1508}15091510for (i = 0; i < code->exceptionTableLength; i++) {1511pc = code->exceptionTable[i].startPC;1512if (pc >= length) {1513errorType = J9NLS_CFR_ERR_HANDLER_START_PC__ID;1514goto _formatError;1515}1516if (!map[pc]) {1517errorType = J9NLS_CFR_ERR_HANDLER_START_TARGET__ID;1518goto _formatError;1519}1520pc = code->exceptionTable[i].endPC;1521if (pc > length) {1522errorType = J9NLS_CFR_ERR_HANDLER_END_PC__ID;1523goto _formatError;1524}1525if ((!map[pc]) && (pc != length)) {1526errorType = J9NLS_CFR_ERR_HANDLER_END_TARGET__ID;1527goto _formatError;1528}1529if (code->exceptionTable[i].startPC >= code->exceptionTable[i].endPC) {1530errorType = J9NLS_CFR_ERR_HANDLER_RANGE_EMPTY__ID;1531goto _formatError;1532}1533pc = code->exceptionTable[i].handlerPC;1534if (pc >= length) {1535errorType = J9NLS_CFR_ERR_HANDLER_PC__ID;1536goto _formatError;1537}1538if (!map[pc]) {1539errorType = J9NLS_CFR_ERR_HANDLER_TARGET__ID;1540goto _formatError;1541}1542}15431544/* Throw a class format error if we are given a static <init> method (otherwise later we will throw a verify error due to back stack shape) */1545info = &(classfile->constantPool[method->nameIndex]);1546if (method->accessFlags & CFR_ACC_STATIC) {1547U_16 returnChar = getReturnTypeFromSignature(classfile->constantPool[method->descriptorIndex].bytes, classfile->constantPool[method->descriptorIndex].slot1, NULL);1548if ((CFR_CONSTANT_Utf8 == info->tag)1549&& J9UTF8_DATA_EQUALS("<init>", 6, info->bytes, info->slot1)1550&& ((J9_IS_CLASSFILE_VALUETYPE(classfile) && !IS_QTYPE(returnChar))1551|| (!J9_IS_CLASSFILE_VALUETYPE(classfile) && IS_QTYPE(returnChar)))1552) {1553errorType = J9NLS_CFR_ERR_ILLEGAL_METHOD_MODIFIERS__ID;1554goto _formatError;1555}1556}15571558if ((flags & J9_VERIFY_IGNORE_STACK_MAPS) == 0) {1559StackmapExceptionDetails exceptionDetails;1560memset(&exceptionDetails, 0, sizeof(exceptionDetails));1561result = checkStackMap(classfile, method, code, map, flags, &exceptionDetails);1562if (result) {1563if (result == FALLBACK_VERIFY_ERROR) {1564errorType = J9NLS_CFR_ERR_INVALID_STACK_MAP_ATTRIBUTE__ID;1565Trc_STV_checkMethodStructure_VerifyError(errorType, methodIndex, pc);1566/* Jazz 82615: Store error data for stackmap frame when verification error occurs */1567buildMethodErrorWithExceptionDetails(error,1568errorType,15690,1570CFR_ThrowVerifyError,1571(I_32)methodIndex,1572(U_32)pc,1573method,1574classfile->constantPool,15750,1576exceptionDetails.stackmapFrameIndex,1577exceptionDetails.stackmapFrameBCI);1578result = -1;1579goto _leaveProc;1580} else {1581errorType = J9NLS_CFR_ERR_INVALID_STACK_MAP_ATTRIBUTE__ID;1582goto _formatError;1583}1584}1585}15861587result = checkBytecodeStructure (classfile, methodIndex, length, map, error, flags, hasRET);15881589if (result) {1590goto _leaveProc;1591}15921593/* Should check thrown exceptions. */15941595goto _leaveProc; /* All is well */15961597_formatError:1598Trc_STV_checkMethodStructure_FormatError(errorType, methodIndex);1599buildMethodError(error, errorType, CFR_ThrowClassFormatError, (I_32)methodIndex, (U_32)pc, method, classfile->constantPool);1600result = -1;1601goto _leaveProc;160216031604_leaveProc:1605if (map && (map != instructionMap)) {1606j9mem_free_memory (map);1607}16081609return result;1610}1611161216131614/*1615##class format checking16161617Check the Method provided and determine the1618referenced constant pool entries.16191620Returns 0 on success, -1 on structure problem (error set), -2 on out of memory.16211622*/16231624IDATA1625j9bcv_verifyClassStructure (J9PortLibrary * portLib, J9CfrClassFile * classfile, U_8 * segment,1626U_8 * segmentLength, U_8 * freePointer, U_32 vmVersionShifted, U_32 flags, I_32 *hasRET)1627{1628UDATA i;1629IDATA isInit;1630IDATA result = 0;1631UDATA length = 0;1632U_16 errorType = 0;1633J9CfrConstantPoolInfo *info;1634J9CfrConstantPoolInfo *utf8;1635J9CfrMethod *method;16361637Trc_STV_j9bcv_verifyClassStructure_Entry(classfile->constantPool[classfile->constantPool[classfile->thisClass].slot1].slot1,1638classfile->constantPool[classfile->constantPool[classfile->thisClass].slot1].bytes);16391640for (i = 1; i < classfile->constantPoolCount; i++) {1641J9CfrConstantPoolInfo *nameAndSig;1642IDATA arity;1643UDATA end;1644IDATA argCount;16451646info = &classfile->constantPool[i];1647switch (info->tag) {1648case CFR_CONSTANT_Class:1649/* Must be a UTF8. */1650utf8 = &classfile->constantPool[info->slot1];1651arity = bcvCheckClassName(utf8);1652if (arity < 0) {1653errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;1654goto _formatError;1655}16561657if (arity > 0) { /* we have some sort of array */1658if (arity > 255) {1659errorType = J9NLS_CFR_ERR_TOO_MANY_DIMENSIONS__ID;1660goto _formatError;1661}1662end = utf8->slot1;16631664switch (utf8->bytes[arity]) {1665case 'L': /* object array */1666if (utf8->bytes[--end] != ';') {1667errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;1668goto _formatError;1669}1670break;1671case 'B': /* base type array */1672case 'C':1673case 'D':1674case 'F':1675case 'I':1676case 'J':1677case 'S':1678case 'Z':1679if (--end != (UDATA) arity) {1680errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;1681goto _formatError;1682}1683break;1684default:1685errorType = J9NLS_CFR_ERR_BAD_CLASS_NAME__ID;1686goto _formatError;1687}1688}16891690break;16911692case CFR_CONSTANT_NameAndType:1693if (0 != (flags & CFR_Xfuture)) {1694/* TODO: use the flags field to determine if this entry has been verified already */1695utf8 = &classfile->constantPool[info->slot2]; /* get the descriptor */1696if ((U_8) '(' == (utf8->bytes)[0]) { /* method descriptor */1697if (bcvCheckMethodName(&classfile->constantPool[info->slot1]) < 0) {1698errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;1699goto _formatError;1700}1701if (j9bcv_checkMethodSignature(&classfile->constantPool[info->slot2], FALSE) < 0) {1702errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;1703goto _formatError;1704}1705} else {1706result = j9bcv_checkFieldSignature(utf8, 0);1707if (result < 0) {1708if (result == -1) {1709errorType = J9NLS_CFR_ERR_BC_FIELD_INVALID_SIG__ID;1710goto _formatError;1711} else {1712errorType = J9NLS_CFR_ERR_TOO_MANY_DIMENSIONS__ID;1713goto _formatError;1714}1715} else {1716result = 0;1717}1718}1719}1720break;1721case CFR_CONSTANT_Dynamic: /* fall through */1722/* No static constraints defined (so far) on slot1 (bsmIndex) */1723case CFR_CONSTANT_Fieldref:1724nameAndSig = &classfile->constantPool[info->slot2];1725utf8 = &classfile->constantPool[nameAndSig->slot1];1726if (bcvCheckName(utf8)) {1727errorType = J9NLS_CFR_ERR_BAD_FIELD_NAME__ID;1728goto _formatError;1729}1730utf8 = &classfile->constantPool[nameAndSig->slot2];1731if ((result = j9bcv_checkFieldSignature(utf8, 0)) < 0) {1732if (result == -1) {1733errorType = J9NLS_CFR_ERR_BC_FIELD_INVALID_SIG__ID;1734goto _formatError;1735} else {1736errorType = J9NLS_CFR_ERR_TOO_MANY_DIMENSIONS__ID;1737goto _formatError;1738}1739} else {1740result = 0;1741}1742break;17431744case CFR_CONSTANT_InvokeDynamic:1745/* No static constraints defined (so far) on slot1 */1746case CFR_CONSTANT_Methodref:1747case CFR_CONSTANT_InterfaceMethodref:1748nameAndSig = &classfile->constantPool[info->slot2];1749utf8 = &classfile->constantPool[nameAndSig->slot1];1750isInit = bcvCheckMethodName(utf8);1751if ((isInit < 0) || ((CFR_METHOD_NAME_CLINIT == isInit) && (CFR_CONSTANT_Methodref == info->tag))) {1752errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;1753goto _formatError;1754}1755info = &classfile->constantPool[nameAndSig->slot2];1756if ((argCount = j9bcv_checkMethodSignature(info, TRUE)) < 0) {1757errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;1758goto _formatError;1759}1760if (isInit) {1761U_16 returnChar = getReturnTypeFromSignature(info->bytes, info->slot1, NULL);1762if ((info->bytes[info->slot1 - 1] != 'V') && !IS_QTYPE(returnChar)) {1763errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;1764goto _formatError;1765}1766}1767if (argCount > 255) {1768errorType = J9NLS_CFR_ERR_TOO_MANY_ARGS__ID;1769/* TODO: determine if this should be verifyError */1770goto _formatError;1771}1772break;17731774case CFR_CONSTANT_MethodType:1775if (j9bcv_checkMethodSignature(&classfile->constantPool[info->slot1], FALSE) < 0) {1776errorType = J9NLS_CFR_ERR_METHODTYPE_INVALID_SIG__ID;1777goto _formatError;1778}1779break;17801781case CFR_CONSTANT_MethodHandle:1782/* method kinds: confirm <init> only when REF_newInvokeSpecial */1783if ((info->slot1 >= MH_REF_INVOKEVIRTUAL) && (info->slot1 <= MH_REF_INVOKEINTERFACE)) {1784J9CfrConstantPoolInfo *methodref = &classfile->constantPool[info->slot2];1785nameAndSig = &classfile->constantPool[methodref->slot2];1786utf8 = &classfile->constantPool[nameAndSig->slot1];1787isInit = bcvIsInitOrClinit(utf8);1788if (CFR_METHOD_NAME_CLINIT == isInit) {1789errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;1790goto _formatError;1791}1792if (CFR_METHOD_NAME_INIT == isInit) {1793if (info->slot1 != MH_REF_NEWINVOKESPECIAL) {1794errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;1795goto _formatError;1796}1797}1798}1799break;18001801}1802}18031804for (i = 0; i < classfile->fieldsCount; i++) {1805J9CfrField *field = &classfile->fields[i];1806info = &classfile->constantPool[field->descriptorIndex];1807utf8 = &classfile->constantPool[field->nameIndex];1808if (j9bcv_checkFieldSignature(info, 0) < 0) {1809errorType = J9NLS_CFR_ERR_BC_FIELD_INVALID_SIG__ID;1810goto _formatError;1811}1812if (bcvCheckName(utf8) < 0) {1813errorType = J9NLS_CFR_ERR_BAD_FIELD_NAME__ID;1814goto _formatError;1815}1816}18171818/* walk the classfile methods list */1819for (i = 0; i < classfile->methodsCount; i++) {1820IDATA argCount = 0;18211822method = &(classfile->methods[i]);1823utf8 = &classfile->constantPool[method->nameIndex];1824if ((isInit = bcvCheckMethodName(utf8)) < 0) {1825info = utf8;1826errorType = J9NLS_CFR_ERR_BAD_METHOD_NAME__ID;1827goto _formatError;1828}18291830info = &classfile->constantPool[method->descriptorIndex];1831argCount = j9bcv_checkMethodSignature(info, TRUE);1832if (argCount < 0) {1833errorType = J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID;1834goto _formatError;1835}18361837/* The requirement for taking no arguments was introduced in Java SE 9.1838* In a class file whose version number is 51.0 or above, the method1839* has its ACC_STATIC flag set and takes no arguments.1840*/1841/* Leave this here to find usages of the following check:1842* J2SE_19 has been deprecated and replaced with J2SE_V111843* if (J2SE_VERSION(vm) >= J2SE_V11) {1844*/1845if (vmVersionShifted >= BCT_JavaMajorVersionShifted(9)) {1846if (classfile->majorVersion >= 51) {1847if ((CFR_METHOD_NAME_CLINIT == isInit)1848&& (0 != argCount)1849) {1850errorType = J9NLS_CFR_ERR_CLINIT_ILLEGAL_SIGNATURE__ID;1851goto _formatError;1852}1853}1854}18551856if (0 == (method->accessFlags & CFR_ACC_STATIC)) {1857argCount++;1858}1859if (argCount > 255) {1860errorType = J9NLS_CFR_ERR_TOO_MANY_ARGS__ID;1861goto _formatError;1862}1863if (method->codeAttribute) {1864if (argCount > (I_32) method->codeAttribute->maxLocals) {1865errorType = J9NLS_CFR_ERR_MAX_LOCALS__ID;1866goto _formatError;1867}1868}1869if (isInit) {1870U_16 returnChar = getReturnTypeFromSignature(info->bytes, info->slot1, NULL);1871if ((J9_IS_CLASSFILE_VALUETYPE(classfile) && !IS_QTYPE(returnChar))1872|| (!J9_IS_CLASSFILE_VALUETYPE(classfile) && (info->bytes[info->slot1 - 1] != 'V'))1873) {1874Trc_STV_j9bcv_verifyClassStructure_MethodError(J9NLS_CFR_ERR_BC_METHOD_INVALID_SIG__ID, i);1875buildMethodError((J9CfrError *)segment, errorType, CFR_ThrowClassFormatError, (I_32) i, 0, method, classfile->constantPool);1876result = -1;1877goto _leaveProc;1878}1879}18801881if (method->codeAttribute) {1882length = method->codeAttribute->codeLength;1883}18841885if ((freePointer + length) < segmentLength) {1886result = checkMethodStructure(portLib, classfile, i, freePointer, (J9CfrError *) segment, flags, hasRET);1887} else {1888/* We should probably skip this -- since if we don't have enough memory, we should just bail */1889result = checkMethodStructure(portLib, classfile, i, NULL, (J9CfrError *) segment, flags, hasRET);1890}18911892if (result) {1893goto _leaveProc; /* Fail */1894}1895}18961897goto _leaveProc; /* All is well */18981899_formatError:1900Trc_STV_j9bcv_verifyClassStructure_ClassError(errorType, info->romAddress);1901buildError((J9CfrError *)segment, errorType, CFR_ThrowClassFormatError, info->romAddress);1902result = -1;19031904_leaveProc:1905Trc_STV_j9bcv_verifyClassStructure_Exit();1906return result;1907}190819091910