{"record":{"id":"5e4e10be6b5280af","repo":"prestodb/presto","slug":"otheroffset-d-length-d-are-invalid-for-othersli-5e4e10","errorCode":null,"errorMessage":"otherOffset %d, length %d are invalid for otherSlice with length %d","messagePattern":"otherOffset (.+?), length (.+?) are invalid for otherSlice with length (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlockBuilder.java","lineNumber":293,"sourceCode":"     * Is the byte sequences at the {@code position + offset} position in the 128-bit values of {@code length} bytes equal\n     * to the byte sequence at {@code otherOffset} in {@code otherSlice}.\n     *\n     * @param position The position of 128-bit integer.\n     * @param offset The offset to the position in the unit of 128-bit integers.\n     * For example, offset = 1 means the next position (one 128-bit integer or 16 bytes) to the specified position.\n     * This means we always compare starting at 128-bit integer boundaries.\n     * @param otherSlice The slice to compare to.\n     * @param otherOffset The offset in bytes to the start of otherSlice.\n     * @param length The length to compare in bytes. It has to be a multiple of 16.\n     * @return True if the bytes are the same, false otherwise.\n     */\n    @Override\n    public boolean bytesEqual(int position, int offset, Slice otherSlice, int otherOffset, int length)\n    {\n        int num128Integers = getNum128Integers(length);\n        checkValidRegion(positionCount, position + offset, num128Integers);\n        if (otherOffset < 0 || length < 0 || otherOffset + length > otherSlice.length()) {\n            throw new IllegalArgumentException(format(\"otherOffset %d, length %d are invalid for otherSlice with length %d\", otherOffset, length, otherSlice.length()));\n        }\n\n        int currentPosition = (position + offset + getOffsetBase()) * 2;\n        for (int i = 0; i < num128Integers; i++) {\n            if (values[currentPosition] != otherSlice.getLong(otherOffset) || values[currentPosition + 1] != otherSlice.getLong(otherOffset + SIZE_OF_LONG)) {\n                return false;\n            }\n\n            currentPosition += 2;\n            otherOffset += SIZE_OF_LONG * 2;\n        }\n\n        return true;\n    }\n\n    @Override\n    public boolean mayHaveNull()\n    {","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlockBuilder.java#L275-L311","documentation":"bytesEqual compares a region of this Int128 block against a byte region of another Slice. Before reading, it validates that otherOffset and length fall inside otherSlice; negative values or a range past the slice end throw IllegalArgumentException with the offending numbers.","triggerScenarios":"Calling bytesEqual(position, offset, otherSlice, otherOffset, length) where otherOffset < 0, length < 0, or otherOffset + length > otherSlice.length() — e.g. a length computed in 128-bit units but applied as bytes against a shorter slice.","commonSituations":"Equality/hash join comparison code passing mismatched lengths; comparing a fixed 16-byte constant slice with a length derived from the block region; corrupted or truncated slices from deserialization.","solutions":["Validate otherOffset >= 0 && length >= 0 && otherOffset + length <= otherSlice.length() before calling bytesEqual.","Ensure length is expressed in bytes consistent with the slice, matching the block region length.","Check that otherSlice was constructed from the full expected payload (not truncated) before comparison."],"exampleFix":"// before\nblock.bytesEqual(pos, 0, shortSlice, 0, 16); // throws if shortSlice.length() < 16\n// after\nif (shortSlice.length() >= 16) {\n    block.bytesEqual(pos, 0, shortSlice, 0, 16);\n}","handlingStrategy":"validation","validationCode":"if (otherOffset < 0 || length < 0 || otherOffset + length > otherSlice.length()) {\n    throw new IllegalArgumentException(\"otherSlice range out of bounds\");\n}\nboolean eq = block.bytesEqual(position, offset, otherSlice, otherOffset, length);","typeGuard":"boolean sliceRangeValid(Slice s, int offset, int length) {\n    return offset >= 0 && length >= 0 && offset + length <= s.length();\n}","tryCatchPattern":"try {\n    return block.bytesEqual(position, offset, otherSlice, otherOffset, length);\n} catch (IllegalArgumentException e) {\n    return false; // treat out-of-range region as unequal\n}","preventionTips":["Always size comparison slices to at least the block region's byte length (16 per Int128 value)","Compute lengths in bytes consistently on both sides","Validate slices deserialized from external sources before comparing"],"tags":["presto","block","illegal-argument","slice","bounds-check"],"backgroundTag":"slice-bounds-violation","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"}