{"record":{"id":"176aaa72bce23fe5","repo":"prestodb/presto","slug":"otheroffset-d-length-d-are-invalid-for-othersli","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/Int128ArrayBlock.java","lineNumber":213,"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 + positionOffset) * 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":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlock.java#L195-L231","documentation":"bytesEqual compares a 128-bit value region of this block against a byte range of another Slice. The otherOffset/length pair must lie entirely within otherSlice (both non-negative and otherOffset + length <= otherSlice.length()); otherwise the comparison would read past the slice, so IllegalArgumentException is thrown.","triggerScenarios":"Calling Int128ArrayBlock.bytesEqual(position, offset, otherSlice, otherOffset, length) where otherOffset < 0, length < 0, or otherOffset + length > otherSlice.length() — e.g. passing a Slice not sliced to the value boundary, or a length other than 16 in 128-bit comparisons.","commonSituations":"Hash/equality operators passing raw slices without adjusting an offset for the value start; comparing DECIMAL values against varbinary slices whose lengths differ; forgetful slicing after copying a sub-range of a larger buffer.","solutions":["Slice otherSlice to exactly the value being compared before calling: otherSlice = slice.slice(valueStart, INT128_BYTES).","Validate otherOffset >= 0 && length >= 0 && otherOffset + length <= otherSlice.length() at the call site.","Ensure length is a multiple of 16 for INT128 comparisons (getNum128Integers expects this)."],"exampleFix":"// before\nblock.bytesEqual(pos, 0, bigSlice, rawOffset, 8); // wrong length/bounds\n// after\nSlice value = bigSlice.slice(valueStart, Int128ArrayBlock.INT128_BYTES);\nblock.bytesEqual(pos, 0, value, 0, Int128ArrayBlock.INT128_BYTES);","handlingStrategy":"validation","validationCode":"checkArgument(otherOffset >= 0 && length >= 0 && otherOffset + length <= otherSlice.length(),\n    \"bytesEqual range [%d, %d) out of slice length %d\", otherOffset, otherOffset + length, otherSlice.length());","typeGuard":"boolean sliceRangeInBounds(Slice slice, int offset, int length) {\n    return offset >= 0 && length >= 0 && offset + length <= slice.length();\n}","tryCatchPattern":"try {\n    equal = block.bytesEqual(position, 0, otherSlice, otherOffset, length);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"are invalid for otherSlice\")) {\n        throw new IllegalStateException(\"comparison slice not aligned to INT128 value boundaries\", e);\n    }\n    throw e;\n}","preventionTips":["Always slice the comparison Slice to exactly the value (16 bytes) before bytesEqual.","Use the type's fixed size constant (INT128_BYTES) for lengths, not the raw slice length.","Cover DECIMAL equality/hash operators with tests using boundary slices."],"tags":["presto","block","int128","bounds-check","illegal-argument"],"backgroundTag":"slice-bounds-mismatch","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"}