{"record":{"id":"dfe7233b72f58f70","repo":"oracle/graal","slug":"branch-target-d-out-of-bounds","errorCode":null,"errorMessage":"Branch target %d out of bounds","messagePattern":"Branch target (.+?) out of bounds","errorType":"exception","errorClass":"BranchTargetOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64MacroAssembler.java","lineNumber":2124,"sourceCode":"        } else {\n            throw GraalError.shouldNotReachHereUnexpectedValue(instruction); // ExcludeFromJacocoGeneratedReport\n        }\n    }\n\n    /**\n     * Patches jump targets when label gets bound.\n     */\n    @Override\n    protected void patchJumpTarget(int patchPos, int jumpTarget) {\n        final int instruction = getInt(patchPos);\n        final int pcRelativeOffset = jumpTarget - patchPos;\n        assert (pcRelativeOffset & 0b11) == 0 : \"unexpected alignment \" + pcRelativeOffset;\n        PatchLabelKind type = PatchLabelKind.fromEncoding(instruction);\n        final int extraInformation = PatchLabelKind.decodeExtraInformation(instruction);\n        switch (type) {\n            case BRANCH_CONDITIONALLY:\n                if (!NumUtil.isSignedNbit(21, pcRelativeOffset)) {\n                    throw new BranchTargetOutOfBoundsException(true, \"Branch target %d out of bounds\", pcRelativeOffset);\n                }\n                ConditionFlag condition = ConditionFlag.fromEncoding(extraInformation);\n                super.b(condition, pcRelativeOffset, patchPos);\n                break;\n            case BRANCH_UNCONDITIONALLY:\n                super.b(pcRelativeOffset, patchPos);\n                break;\n            case COMPARE_REG_BRANCH_NONZERO:\n            case COMPARE_REG_BRANCH_ZERO: {\n                if (!NumUtil.isSignedNbit(21, pcRelativeOffset)) {\n                    throw new BranchTargetOutOfBoundsException(true, \"Branch target %d out of bounds\", pcRelativeOffset);\n                }\n                int regEncoding = extraInformation >>> 1;\n                int sizeEncoding = extraInformation & 1;\n                Register reg = AArch64.cpuRegisters.get(regEncoding);\n                // 1 => 64; 0 => 32\n                int size = sizeEncoding == 1 ? 64 : 32;\n                if (type == PatchLabelKind.COMPARE_REG_BRANCH_NONZERO) {","sourceCodeStart":2106,"sourceCodeEnd":2142,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64MacroAssembler.java#L2106-L2142","documentation":"Thrown by readPrimitiveArrayUnaligned when offset < 0 or offset + kind.getByteCount() exceeds the Value's buffer size. This mirrors native unaligned read semantics (offset in bytes from the array start) so the guard ensures the full multi-byte read lies inside the buffer.","triggerScenarios":"Negative offsets; offsets near the end of the buffer (e.g. reading a long at len-4); byte offsets computed for a differently-sized array; offsets in element units mistakenly used as byte offsets.","commonSituations":"Host code ported from Unsafe.getObject-style reads where offsets included object-header constants that differ in the guest; byte-offset math after layout changes between JVM versions; reading the last element with an inclusive-end off-by-one.","solutions":["Clamp/validate: require 0 <= offset && offset + kind.getByteCount() <= bufferSize before calling","Recompute offsets against the guest layout (use the vm access layout API, do not reuse host Unsafe offsets)","For trailing partial data, read fewer bytes or reject the operation explicitly rather than letting it throw"],"exampleFix":"// before\nJavaConstant v = vmAccess.readPrimitiveArrayUnaligned(array, JavaKind.Long, offset);\n\n// after\nlong bufSize = ((EspressoExternalObjectConstant) array).getValue().getBufferSize();\nif (offset >= 0 && offset + JavaKind.Long.getByteCount() <= bufSize) {\n    JavaConstant v = vmAccess.readPrimitiveArrayUnaligned(array, JavaKind.Long, offset);\n} else {\n    throw new IndexOutOfBoundsException(\"offset \" + offset + \" out of range for \" + bufSize);\n}","handlingStrategy":"validation","validationCode":"long bufSize = ((EspressoExternalObjectConstant) array).getValue().getBufferSize();\nint byteCount = kind.getByteCount();\nif (offset < 0 || offset + byteCount > bufSize) {\n    throw new IndexOutOfBoundsException(\"read [\" + offset + \",\" + (offset + byteCount) + \") outside buffer of \" + bufSize);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember offsets are byte offsets into the array's interop buffer, native-endian, matching hosted unaligned reads — do not reuse host Unsafe offsets blindly","Always check offset + kind.getByteCount() <= bufferSize before the final element of an array"],"tags":["espresso","jvmci","unaligned-read","bounds-check","offset"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}