String Index Always Out Of Bounds

ID

java.string_index_out_of_bounds

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

reliability

Description

Reports a narrow, literal-only subset of String index calls (charAt, substring, codePointAt, the two-argument indexOf/lastIndexOf, and setCharAt on StringBuilder/StringBuffer) that always throw StringIndexOutOfBoundsException: a negative literal index, a substring(a, b) with both literal and a > b, or an index that is the same string’s own length() (or length() plus a literal offset that is still out of range).

This is a subset of the defect by design: no value is tracked through a variable, so charAt(i) for a plain variable i is never reported, and a call on a different receiver than the one whose length() is used (a.charAt(b.length())) is never decided. Upstream’s own check additionally tracks a literal string receiver’s exact length ("str".substring(25)) and a handful of further methods (codePointCount, getChars, subSequence, offsetByCodePoints); this rule reports neither.

Rationale

Every one of these calls throws unconditionally once the index is out of range — there is no partial result, only an exception. One example per reported category:

String speech = "Lorem ipsum dolor sit amet";

char none = speech.charAt(-1);               // (1) negative literal index
String tail = speech.substring(9, 4);        // (2) substring(a, b), both literal, a > b
char last = speech.charAt(speech.length());  // (3) the receiver's own length() as an index

Because the index is a literal, or a literal offset from the very string being indexed, the crash is guaranteed on every execution path that reaches the line — it is not a corner case that only shows up with unusual input.

Remediation

Use an index that is provably within 0 and length() - 1 (or length() itself for `substring’s end index):

String speech = "Lorem ipsum dolor sit amet";

char first = speech.charAt(0);                        // Compliant
String tail = speech.substring(4, 9);                 // Compliant - begin before end
char last = speech.charAt(speech.length() - 1);       // Compliant
String whole = speech.substring(0, speech.length());  // Compliant - length() is a valid end index

© 2026 Xygeni. All rights reserved