{"record":{"id":"90a6a6c8d9bb2bea","repo":"java-native-access/jna","slug":"invalid-offset-off","errorCode":null,"errorMessage":"Invalid offset: <off>","messagePattern":"Invalid offset: <off>","errorType":"validation","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"src/com/sun/jna/Memory.java","lineNumber":219,"sourceCode":"    }\n\n    /** Returns false if the memory has been freed. */\n    public boolean valid() {\n        return peer != 0;\n    }\n\n    public long size() {\n        return size;\n    }\n\n    /**\n     * Check that indirection won't cause us to write outside the\n     * malloc'ed space.\n     *\n     */\n    protected void boundsCheck(long off, long sz) {\n        if (off < 0) {\n            throw new IndexOutOfBoundsException(\"Invalid offset: \" + off);\n        }\n        if (off + sz > size) {\n            String msg = \"Bounds exceeds available space : size=\"\n                + size + \", offset=\" + (off + sz);\n            throw new IndexOutOfBoundsException(msg);\n        }\n    }\n\n    //////////////////////////////////////////////////////////////////////////\n    // Raw read methods\n    //////////////////////////////////////////////////////////////////////////\n\n    /**\n     * Indirect the native pointer to <code>malloc</code> space, a la\n     * <code>Pointer.read</code>.  But this method performs a bounds\n     * checks to ensure that the indirection does not cause memory outside the\n     * <code>malloc</code>ed space to be accessed.\n     *","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/src/com/sun/jna/Memory.java#L201-L237","documentation":"Memory.boundsCheck() validates every read/write offset against the allocated block. A negative offset can never point into valid malloc'ed space, so JNA throws IndexOutOfBoundsException immediately before any size check.","triggerScenarios":"Any Memory read/write method (readInt, getPointer, setString, read(offset, buf, 0, len), etc.) called with a negative offset — typically from arithmetic on a bad pointer, a negative share() offset, or unsigned/signed confusion producing a negative long.","commonSituations":"Computing offsets from struct field offsets that overflowed; passing a negative result of (ptr - base) arithmetic; reading at pointer.getValue() - delta where the pointer was smaller than the delta.","solutions":["Fix the offset computation so it is non-negative; check the arithmetic that produced it.","Validate offsets before access: if (off < 0) handle/throw a clearer error.","If working with a sub-region, use Memory.share(offset, size) with correct bounds instead of manual offset math.","Verify the native pointer you derived the offset from is valid (Pointer.NULL checks)."],"exampleFix":"// before\nint v = memory.readInt(fieldOffset); // fieldOffset == -8 -> IndexOutOfBoundsException\n// after\nif (fieldOffset < 0) {\n    throw new IllegalStateException(\"bad field offset \" + fieldOffset);\n}\nint v = memory.readInt(fieldOffset);","handlingStrategy":"validation","validationCode":"if (offset < 0) {\n    throw new IllegalArgumentException(\"negative offset: \" + offset);\n}\nmemory.readInt(offset);","typeGuard":"boolean validOffset(Memory m, long off, long sz) {\n    return off >= 0 && off + sz <= m.size();\n}","tryCatchPattern":"try {\n    value = memory.readInt(offset);\n} catch (IndexOutOfBoundsException e) {\n    log.warn(\"bad memory offset {}\", offset, e);\n    value = 0; // or rethrow as a domain error\n}","preventionTips":["Compute offsets with unsigned-safe arithmetic; check for negative results after subtraction.","Use struct classes (Structure) instead of raw offset math where possible.","Keep base pointer and delta arithmetic in one helper that validates the result."],"tags":["jna","native-memory","bounds-check","index-out-of-bounds"],"backgroundTag":"index-out-of-bounds","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}