Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/htsjdk/samtools/cram/io/LTF8.java
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public static int writeUnsignedLTF8(final long value, final OutputStream outputS
outputStream.write((int) ((value >> 48) & 0xFF));
outputStream.write((int) ((value >> 40) & 0xFF));
outputStream.write((int) ((value >> 32) & 0xFF));
outputStream.write((int) ((value >> 28) & 0xFF));
outputStream.write((int) ((value >> 24) & 0xFF));
outputStream.write((int) ((value >> 16) & 0xFF));
outputStream.write((int) ((value >> 8) & 0xFF));
outputStream.write((int) (value & 0xFF));
Expand Down
41 changes: 41 additions & 0 deletions src/test/java/htsjdk/samtools/cram/io/LTF8Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,47 @@ public void testPredefined (long value, byte[] ltf8) throws IOException {
}
}

/**
* Tests the 9-byte (full 64-bit) LTF8 encoding with a value where bits [35:32] differ from
* bits [27:24], which exposes the >> 28 vs >> 24 bug in writeUnsignedLTF8.
*
* For 0x0123456789ABCDEFL:
* (value >> 28) & 0xFF == 0x78 (wrong, old behavior)
* (value >> 24) & 0xFF == 0x89 (correct)
*
* The 9-byte encoding writes a 0xFF prefix followed by bytes at shifts 56,48,40,32,24,16,8,0.
*/
@Test
public void testNineByteEncodingWithDistinctBitsAt24And28() throws IOException {
final long value = 0x0123456789ABCDEFL;

// Expected encoding: 0xFF prefix + 8 bytes at shifts 56,48,40,32,24,16,8,0
final byte[] expectedBytes = {
(byte) 0xFF,
(byte) 0x01, // >> 56
Comment thread
tfenne marked this conversation as resolved.
Outdated
(byte) 0x23, // >> 48
(byte) 0x45, // >> 40
(byte) 0x67, // >> 32
(byte) 0x89, // >> 24 (would be 0x78 with the >> 28 bug)
(byte) 0xAB, // >> 16
(byte) 0xCD, // >> 8
(byte) 0xEF, // >> 0
};

try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
final int bitsWritten = LTF8.writeUnsignedLTF8(value, baos);
Assert.assertEquals(bitsWritten, 72);

final byte[] actualBytes = baos.toByteArray();
Assert.assertEquals(actualBytes, expectedBytes, "9-byte LTF8 encoded bytes do not match expected");

try (ByteArrayInputStream bais = new ByteArrayInputStream(actualBytes)) {
final long decoded = LTF8.readUnsignedLTF8(bais);
Assert.assertEquals(decoded, value, "Round-trip encode/decode mismatch for 9-byte LTF8 value");
}
}
}

@Test(expectedExceptions = RuntimeEOFException.class)
public void emptyStreamTest() throws IOException {
try (InputStream emptyStream = new ByteArrayInputStream(new byte[0])) {
Expand Down
Loading