{"record":{"id":"1fb6ff4d9d8a24ee","repo":"oracle/graal","slug":"fromindex-fromindex","errorCode":null,"errorMessage":"fromIndex = ${fromIndex}","messagePattern":"fromIndex = (.+?)","errorType":"validation","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso.polyglot/src/com/oracle/truffle/espresso/polyglot/collections/AbstractListWithoutField.java","lineNumber":439,"sourceCode":"     *           <p>\n     *           The {@code listIterator(int)} method returns a \"wrapper object\" over a list\n     *           iterator on the backing list, which is created with the corresponding method on the\n     *           backing list. The {@code iterator} method merely returns {@code listIterator()},\n     *           and the {@code size} method merely returns the subclass's {@code size} field.\n     *\n     * @throws IndexOutOfBoundsException if an endpoint index value is out of range\n     *             {@code (fromIndex < 0 || toIndex > size)}\n     * @throws IllegalArgumentException if the endpoint indices are out of order\n     *             {@code (fromIndex > toIndex)}\n     */\n    public List<E> subList(int fromIndex, int toIndex) {\n        subListRangeCheck(fromIndex, toIndex, size());\n        return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex));\n    }\n\n    static void subListRangeCheck(int fromIndex, int toIndex, int size) {\n        if (fromIndex < 0) {\n            throw new IndexOutOfBoundsException(\"fromIndex = \" + fromIndex);\n        }\n        if (toIndex > size) {\n            throw new IndexOutOfBoundsException(\"toIndex = \" + toIndex);\n        }\n        if (fromIndex > toIndex) {\n            throw new IllegalArgumentException(\"fromIndex(\" + fromIndex +\n                            \") > toIndex(\" + toIndex + \")\");\n        }\n    }\n\n    // Comparison and hashing\n\n    /**\n     * Compares the specified object with this list for equality. Returns {@code true} if and only\n     * if the specified object is also a list, both lists have the same size, and all corresponding\n     * pairs of elements in the two lists are <i>equal</i>. (Two elements {@code e1} and {@code e2}\n     * are <i>equal</i> if {@code (e1==null ? e2==null :\n     * e1.equals(e2))}.) In other words, two lists are defined to be equal if they contain the same","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso.polyglot/src/com/oracle/truffle/espresso/polyglot/collections/AbstractListWithoutField.java#L421-L457","documentation":"Thrown by AbstractListWithoutField.subList range checks when the start index is negative. It mirrors java.util.AbstractList semantics: subList(fromIndex, toIndex) requires 0 <= fromIndex <= toIndex <= size. A negative fromIndex is rejected before any sublist view is created.","triggerScenarios":"Calling subList(negative, n) on any Espresso polyglot collections list (e.g. list.subList(-1, 3)); computing an offset that underflows (start - 1 when start == 0); passing a user-supplied paging start index without clamping.","commonSituations":"Pagination code computing 'int start = page * pageSize - pageSize' that goes negative for page 0; passing an index derived from lastIndexOf (which returns -1 on miss) directly to subList.","solutions":["Validate fromIndex >= 0 before calling subList and clamp to 0 when appropriate.","Check for -1 sentinels (indexOf, lastIndexOf) before using them as fromIndex.","Use Math.max(0, fromIndex) when a clamped window is acceptable.","Wrap the call in try-catch on IndexOutOfBoundsException at API boundaries that accept raw user input."],"exampleFix":"// before\nList<E> page = list.subList(start, end); // start can be -1 from lastIndexOf\n\n// after\nint start = Math.max(0, rawStart);\nif (rawStart == -1 /* not found */) return List.of();\nList<E> page = list.subList(start, Math.max(start, end));","handlingStrategy":"validation","validationCode":"if (fromIndex < 0 || toIndex > list.size() || fromIndex > toIndex) {\n    throw new IllegalArgumentException(\"bad range: \" + fromIndex + \"..\" + toIndex + \" of \" + list.size());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize sublist bounds checks in one helper used everywhere.","Treat -1 search results as 'not found', never as an index.","Unit-test boundary ranges (0, size, size+1, inverted)."],"tags":["collections","index-out-of-bounds","sublist","espresso","polyglot"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}