{"record":{"id":"35a273e2f3e4c027","repo":"oracle/graal","slug":"arrayoffset-is-beyond-array-length","errorCode":null,"errorMessage":"arrayOffset is beyond array length","messagePattern":"arrayOffset is beyond array length","errorType":"exception","errorClass":"ArrayIndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_sun_misc_Unsafe.java","lineNumber":580,"sourceCode":"     * @throws IllegalArrayAccessException if the access is out of bounds\n     */\n    private static void boundsCheck(\n                    @JavaType(Object.class) StaticObject o, long offset, long accessSize, EspressoLanguage language) throws IllegalArrayAccessException {\n        // offset = baseOffset + index * indexScale\n        assert o.getKlass().isArray();\n        Klass klass = o.getKlass();\n        int baseOffset = arrayBaseOffset(klass);\n        int indexScale = arrayIndexScale(klass);\n        if (offset < baseOffset) {\n            throw new IllegalArrayAccessException(\"arrayOffset is less than baseOffset\");\n        }\n        /*\n         * Ensure memory is aligned for operations like sub-word CAS that may temporarily access\n         * memory just beyond array bounds.\n         */\n        int maxIndex = alignUpToIntBytes(baseOffset + o.length(language) * indexScale);\n        if (offset > maxIndex - accessSize) {\n            throw new IllegalArrayAccessException(\"arrayOffset is beyond array length\");\n        }\n    }\n\n    /**\n     * Thrown when {@link #boundsCheck} fails due to an out-of-bounds access.\n     */\n    private static class IllegalArrayAccessException extends Exception {\n        @Serial private static final long serialVersionUID = 1L;\n\n        IllegalArrayAccessException(String msg) {\n            super(msg);\n        }\n\n        @SuppressWarnings(\"sync-override\")\n        @Override\n        public final Throwable fillInStackTrace() {\n            return this;\n        }","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_sun_misc_Unsafe.java#L562-L598","documentation":"The upper-bound arm of the same Unsafe boundsCheck: after alignment, if offset > maxIndex - accessSize the access would read past the array's usable memory (including the alignment slack allowed for sub-word CAS). IllegalArrayAccessException('arrayOffset is beyond array length') is thrown.","triggerScenarios":"Guest code using Unsafe with an index >= array.length, an accessSize that overruns the last element (e.g. getLong at the last int slot), or stale offsets after an array shrank/was reallocated.","commonSituations":"Serialization/copy libraries (Kryo-style) doing manual memory copies with Unsafe; off-by-one index math; race where another thread replaced the array between offset computation and access.","solutions":["Clamp indices: ensure index*indexScale + accessSize <= array length * indexScale before the Unsafe call.","Use bulk APIs (arraycopy, ByteBuffer) instead of per-element Unsafe access where possible.","Audit hardcoded scale constants against Unsafe.arrayIndexScale for the actual element type."],"exampleFix":"// before\nunsafe.getLong(arr, base + i * 8); // i can be arr.length -> overrun\n\n// after\nif (i >= 0 && i < arr.length) {\n    unsafe.getLong(arr, base + i * 8L);\n}","handlingStrategy":"validation","validationCode":"long base = unsafe.arrayBaseOffset(arr.getClass());\nlong scale = unsafe.arrayIndexScale(arr.getClass());\nif (offset + accessSize > base + (long) arr.length * scale) throw new IndexOutOfBoundsException();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Range-check index against arr.length before every Unsafe access.","Avoid stale offsets captured before arrays are resized/replaced."],"tags":["espresso","unsafe","bounds-check","off-by-one"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}