{"record":{"id":"cea598d36f9ec5af","repo":"apache/hadoop","slug":"offset-s-is-out-of-range-s-s","errorCode":null,"errorMessage":"offset: %s is out of range [%s, %s]","messagePattern":"offset: (.+?) is out of range \\[(.+?), (.+?)\\]","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/util/FSUtils.java","lineNumber":39,"sourceCode":"import org.apache.hadoop.conf.Configuration;\nimport org.apache.hadoop.fs.FSExceptionMessages;\nimport org.apache.hadoop.fs.FileSystem;\nimport org.apache.hadoop.util.Preconditions;\n\nimport java.net.URI;\n\npublic final class FSUtils {\n  private static final String OVERFLOW_ERROR_HINT =\n      FSExceptionMessages.TOO_MANY_BYTES_FOR_DEST_BUFFER\n          + \": request length = %s, with offset = %s, buffer capacity = %s\";\n\n  private FSUtils() {\n  }\n\n  public static void checkReadParameters(byte[] buffer, int offset, int length) {\n    Preconditions.checkArgument(buffer != null, \"Null buffer\");\n    if (offset < 0 || offset > buffer.length) {\n      throw new IndexOutOfBoundsException(\n          String.format(\"offset: %s is out of range [%s, %s]\", offset, 0, buffer.length));\n    }\n    Preconditions.checkArgument(length >= 0, \"length: %s is negative\", length);\n    if (buffer.length < offset + length) {\n      throw new IndexOutOfBoundsException(\n          String.format(OVERFLOW_ERROR_HINT, length, offset, (buffer.length - offset)));\n    }\n  }\n\n  public static URI normalizeURI(URI fsUri, Configuration hadoopConfig) {\n    final String scheme = fsUri.getScheme();\n    final String authority = fsUri.getAuthority();\n\n    if (scheme == null && authority == null) {\n      fsUri = FileSystem.getDefaultUri(hadoopConfig);\n    } else if (scheme != null && authority == null) {\n      URI defaultUri = FileSystem.getDefaultUri(hadoopConfig);\n      if (scheme.equals(defaultUri.getScheme()) && defaultUri.getAuthority() != null) {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/util/FSUtils.java#L21-L57","documentation":"FSUtils.checkReadParameters validates the (buffer, offset, length) triple before every read on the TOS FileSystem input streams. This IndexOutOfBoundsException fires when offset is negative or greater than buffer.length — the Java contract requires 0 <= offset <= buffer.length. It mirrors org.apache.hadoop.fs.FileSystem#verifyReadParameters and means the caller passed a bad starting position, before length is even considered.","triggerScenarios":"Calling InputStream.read(buffer, offset, length) / FSDataInputStream.readFully variants on a TOS file with a negative offset, or an offset beyond the buffer's length (e.g., offset == buffer.length + 1), including offset > 0 on a zero-length or freshly allocated empty buffer.","commonSituations":"Caller-side bookkeeping bugs: a progress/position accumulator incremented past the buffer size; reusing a length variable as an offset; readFully into a sub-range computed as (buf, remaining, chunk) with arguments transposed; empty buffers from list-driven code where a 0-byte read buffer still gets a nonzero offset.","solutions":["Fix the call site so offset is within [0, buffer.length]; check the argument order — the classic bug is swapping offset and length.","Validate upfront with FSUtils.checkReadParameters(buffer, offset, length) (or equivalent range check) so failures point at your code, not the stack inside the connector.","If the offset came from a loop accumulator, audit the loop bounds and how the buffer is re-sliced between iterations.","Add a unit test asserting reads with edge offsets 0, buffer.length, and negative values behave as intended."],"exampleFix":"// before\nint off = pos; // pos can exceed buf.length\nin.read(buf, off, len);\n\n// after\nFSUtils.checkReadParameters(buf, off, len);\nin.read(buf, Math.max(0, Math.min(off, buf.length)), len);","handlingStrategy":"validation","validationCode":"if (offset < 0 || offset > buffer.length) {\n  throw new IllegalArgumentException(\"bad read offset \" + offset + \" for buffer of \" + buffer.length);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on while ((n = in.read(buf, off, len)) != -1) loops where off/len shrink together.","Unit-test read helpers with offset edge values 0, 1, buffer.length-1, buffer.length.","Watch for swapped (offset, length) arguments at call sites."],"tags":["read","buffer","index-out-of-bounds","argument-validation","input-stream"],"backgroundTag":"buffer-offset-out-of-bounds","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}