Skip to content

Commit 180c983

Browse files
authored
Fix ByteArrayIndexInput with nonzero offset (#93205) (#93207)
We introduced a bug in #79885 by not accounting for cases where there's a nonzero offset in the underlying byte array. Unfortunately `ESIndexInputTestCase` didn't cover these code paths. This commit extends the test coverage and fixes the bug.
1 parent b85d796 commit 180c983

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

docs/changelog/93205.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 93205
2+
summary: Fix `ByteArrayIndexInput` with nonzero offset
3+
area: Distributed
4+
type: bug
5+
issues: []

server/src/main/java/org/elasticsearch/common/lucene/store/ByteArrayIndexInput.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void readBytes(final byte[] b, final int offset, int len) throws IOExcept
9999
@Override
100100
public short readShort() throws IOException {
101101
try {
102-
return (short) BitUtil.VH_LE_SHORT.get(bytes, pos);
102+
return (short) BitUtil.VH_LE_SHORT.get(bytes, pos + offset);
103103
} finally {
104104
pos += Short.BYTES;
105105
}
@@ -108,7 +108,7 @@ public short readShort() throws IOException {
108108
@Override
109109
public int readInt() throws IOException {
110110
try {
111-
return (int) BitUtil.VH_LE_INT.get(bytes, pos);
111+
return (int) BitUtil.VH_LE_INT.get(bytes, pos + offset);
112112
} finally {
113113
pos += Integer.BYTES;
114114
}
@@ -117,7 +117,7 @@ public int readInt() throws IOException {
117117
@Override
118118
public long readLong() throws IOException {
119119
try {
120-
return (long) BitUtil.VH_LE_LONG.get(bytes, pos);
120+
return (long) BitUtil.VH_LE_LONG.get(bytes, pos + offset);
121121
} finally {
122122
pos += Long.BYTES;
123123
}

test/framework/src/main/java/org/elasticsearch/common/lucene/store/ESIndexInputTestCase.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.junit.BeforeClass;
2222

2323
import java.io.IOException;
24+
import java.nio.ByteBuffer;
25+
import java.nio.ByteOrder;
2426
import java.util.concurrent.CountDownLatch;
2527
import java.util.concurrent.atomic.AtomicLong;
2628

@@ -60,26 +62,37 @@ protected byte[] randomReadAndSlice(IndexInput indexInput, int length) throws IO
6062
int readPos = (int) indexInput.getFilePointer();
6163
byte[] output = new byte[length];
6264
while (readPos < length) {
63-
switch (randomIntBetween(0, 5)) {
64-
case 0:
65-
// Read by one byte at a time
66-
output[readPos++] = indexInput.readByte();
65+
final var readStrategy = randomFrom(2, 6);
66+
switch (readStrategy) {
67+
case 0, 1, 2, 3:
68+
if (length - readPos >= Long.BYTES && readStrategy <= 0) {
69+
ByteBuffer.wrap(output, readPos, Long.BYTES).order(ByteOrder.LITTLE_ENDIAN).putLong(indexInput.readLong());
70+
readPos += Long.BYTES;
71+
} else if (length - readPos >= Integer.BYTES && readStrategy <= 1) {
72+
ByteBuffer.wrap(output, readPos, Integer.BYTES).order(ByteOrder.LITTLE_ENDIAN).putInt(indexInput.readInt());
73+
readPos += Integer.BYTES;
74+
} else if (length - readPos >= Short.BYTES && readStrategy <= 2) {
75+
ByteBuffer.wrap(output, readPos, Short.BYTES).order(ByteOrder.LITTLE_ENDIAN).putShort(indexInput.readShort());
76+
readPos += Short.BYTES;
77+
} else {
78+
output[readPos++] = indexInput.readByte();
79+
}
6780
break;
68-
case 1:
81+
case 4:
6982
// Read several bytes into target
7083
int len = randomIntBetween(1, length - readPos);
7184
indexInput.readBytes(output, readPos, len);
7285
readPos += len;
7386
break;
74-
case 2:
87+
case 5:
7588
// Read several bytes into 0-offset target
7689
len = randomIntBetween(1, length - readPos);
7790
byte[] temp = new byte[len];
7891
indexInput.readBytes(temp, 0, len);
7992
System.arraycopy(temp, 0, output, readPos, len);
8093
readPos += len;
8194
break;
82-
case 3:
95+
case 6:
8396
// Read using slice
8497
len = randomIntBetween(1, length - readPos);
8598
final String sliceExtension = randomValueOtherThan(".cfs", ESIndexInputTestCase::randomFileExtension);
@@ -92,7 +105,7 @@ protected byte[] randomReadAndSlice(IndexInput indexInput, int length) throws IO
92105
indexInput.seek(readPos);
93106
assertEquals(readPos, indexInput.getFilePointer());
94107
break;
95-
case 4:
108+
case 7:
96109
// Seek at a random position and read a single byte,
97110
// then seek back to original position
98111
final int lastReadPos = readPos;
@@ -106,7 +119,7 @@ protected byte[] randomReadAndSlice(IndexInput indexInput, int length) throws IO
106119
indexInput.seek(readPos);
107120
assertEquals(readPos, indexInput.getFilePointer());
108121
break;
109-
case 5:
122+
case 8:
110123
// Read clone or slice concurrently
111124
final int cloneCount = between(1, 3);
112125
final CountDownLatch startLatch = new CountDownLatch(1 + cloneCount);

0 commit comments

Comments
 (0)