Skip to content

Commit 925a9a3

Browse files
authored
Fix byte array iterator (#106372)
If ByteArray has been resized, the byte iterator can access null pages. When resizing a big array, we overly allocate the pages array and assign null to the extra pages. Relates #106270
1 parent ed33fdd commit 925a9a3

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

server/src/main/java/org/elasticsearch/common/util/BigByteArray.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,17 @@ public byte[] array() {
146146
public BytesRefIterator iterator() {
147147
return new BytesRefIterator() {
148148
int i = 0;
149+
long remained = size;
149150

150151
@Override
151152
public BytesRef next() {
152-
if (i >= pages.length) {
153+
if (remained == 0) {
153154
return null;
154155
}
155-
int len = i == pages.length - 1 ? Math.toIntExact(size - (pages.length - 1L) * PAGE_SIZE_IN_BYTES) : PAGE_SIZE_IN_BYTES;
156-
return new BytesRef(pages[i++], 0, len);
156+
byte[] page = pages[i++];
157+
int len = Math.toIntExact(Math.min(page.length, remained));
158+
remained -= len;
159+
return new BytesRef(page, 0, len);
157160
}
158161
};
159162
}

server/src/test/java/org/elasticsearch/common/util/BigArraysTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,19 @@ public void testByteIterator() throws Exception {
371371
}
372372
}
373373
assertThat(offset, equalTo(bytes.length));
374+
int newLen = randomIntBetween(bytes.length, bytes.length + 100_000);
375+
array = bigArrays.resize(array, newLen);
376+
it = array.iterator();
377+
offset = 0;
378+
while ((ref = it.next()) != null) {
379+
for (int i = 0; i < ref.length; i++) {
380+
if (offset < bytes.length) {
381+
assertEquals(bytes[offset], ref.bytes[ref.offset + i]);
382+
}
383+
offset++;
384+
}
385+
}
386+
assertThat(offset, equalTo(newLen));
374387
array.close();
375388
}
376389

0 commit comments

Comments
 (0)