{"record":{"id":"35d3864f2fca3ba6","repo":"prestodb/presto","slug":"arrayoffset-is-negative-35d386","errorCode":null,"errorMessage":"arrayOffset is negative","messagePattern":"arrayOffset is negative","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/ShortArrayBlock.java","lineNumber":57,"sourceCode":"    public static final int SIZE_IN_BYTES_PER_POSITION = Short.BYTES + Byte.BYTES;\n\n    private final int arrayOffset;\n    private final int positionCount;\n    @Nullable\n    private final boolean[] valueIsNull;\n    private final short[] values;\n\n    private final long retainedSizeInBytes;\n\n    public ShortArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, short[] values)\n    {\n        this(0, positionCount, valueIsNull.orElse(null), values);\n    }\n\n    ShortArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, short[] values)\n    {\n        if (arrayOffset < 0) {\n            throw new IllegalArgumentException(\"arrayOffset is negative\");\n        }\n        this.arrayOffset = arrayOffset;\n        if (positionCount < 0) {\n            throw new IllegalArgumentException(\"positionCount is negative\");\n        }\n        this.positionCount = positionCount;\n\n        if (values.length - arrayOffset < positionCount) {\n            throw new IllegalArgumentException(\"values length is less than positionCount\");\n        }\n        this.values = values;\n\n        if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {\n            throw new IllegalArgumentException(\"isNull length is less than positionCount\");\n        }\n        this.valueIsNull = valueIsNull;\n\n        retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/ShortArrayBlock.java#L39-L75","documentation":"ShortArrayBlock stores a shared backing array with an offset window into it; the package-private constructor validates that arrayOffset and positionCount are non-negative so that position indexing (arrayOffset + position) is always in bounds. A negative arrayOffset indicates corrupted slice parameters and fails fast with IllegalArgumentException.","triggerScenarios":"Constructing ShortArrayBlock with a negative arrayOffset — typically only reachable from internal factory methods (wrapSlice, getRegion copying, block compaction) that compute offsets via subtraction or slicing of a parent block.","commonSituations":"Custom block code copying regions with wrong start offsets; regression in block compaction/retention logic after block layout changes between Presto versions.","solutions":["Check offset arguments are >= 0 before invoking the constructor (or its factory methods)","Fix the offset computation (e.g. a start index that went negative) in the calling block code","Upgrade/regress to a Presto version without the block-slicing bug if this arises from internal compaction code"],"exampleFix":"// before\nreturn new ShortArrayBlock(offset, count, valueIsNull, values); // offset computed, may be negative\n// after\ncheckArgument(offset >= 0, \"arrayOffset is negative: %s\", offset);\nreturn new ShortArrayBlock(offset, count, valueIsNull, values);","handlingStrategy":"validation","validationCode":"// before constructing ShortArrayBlock (or calling factories that slice)\nif (arrayOffset < 0) {\n    throw new IllegalArgumentException(\"arrayOffset computed as \" + arrayOffset + \" is negative\");\n}\n","typeGuard":null,"tryCatchPattern":"try {\n    return new ShortArrayBlock(arrayOffset, positionCount, valueIsNull, values);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().equals(\"arrayOffset is negative\")) {\n        throw new IllegalStateException(\"negative slice offset \" + arrayOffset + \"; check slicing arithmetic\", e);\n    }\n    throw e;\n}","preventionTips":["Validate start/offset arithmetic before slicing blocks","Clamp offsets with Math.max(0, ...) where underflow is possible","Add assertions in block-region-copy helpers that offsets are non-negative"],"tags":["presto","shortarrayblock","argument-validation","blocks"],"backgroundTag":"negative-offset-argument","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}