Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 2.4] Fix bug in SlicedInputStream with zero length #5044

Merged
merged 1 commit into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,10 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Better plural stemmer than minimal_english ([#4738](https://github.com/opensearch-project/OpenSearch/pull/4738))
- Fix AbstractStringFieldDataTestCase tests to account for TotalHits lower bound ([4867](https://github.com/opensearch-project/OpenSearch/pull/4867))
- [Segment Replication] Fix bug of replica shard's translog not purging on index flush when segment replication is enabled ([4975](https://github.com/opensearch-project/OpenSearch/pull/4975))
- Fix bug in SlicedInputStream with zero length ([#4863](https://github.com/opensearch-project/OpenSearch/pull/4863))
-

### Security

[Unreleased]: https://github.com/opensearch-project/OpenSearch/compare/2.2.0...HEAD
[2.x]: https://github.com/opensearch-project/OpenSearch/compare/2.2.0...2.x
[2.x]: https://github.com/opensearch-project/OpenSearch/compare/2.2.0...2.x
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

/**
* A {@link SlicedInputStream} is a logical
Expand Down Expand Up @@ -100,6 +101,11 @@ public final int read() throws IOException {

@Override
public final int read(byte[] buffer, int offset, int length) throws IOException {
Objects.checkFromIndexSize(offset, length, buffer.length);
if (length == 0) {
return 0;
}

final InputStream stream = currentStream();
if (stream == null) {
return -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@
package org.opensearch.index.snapshots.blobstore;

import com.carrotsearch.randomizedtesting.generators.RandomNumbers;

import org.hamcrest.MatcherAssert;
import org.opensearch.test.OpenSearchTestCase;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import static org.hamcrest.Matchers.equalTo;
Expand Down Expand Up @@ -86,11 +91,9 @@ protected InputStream openSlice(int slice) throws IOException {
assertThat(random.nextInt(Byte.MAX_VALUE), equalTo(input.read()));
break;
default:
byte[] b = randomBytes(random);
byte[] buffer = new byte[b.length];
int read = readFully(input, buffer);
assertThat(b.length, equalTo(read));
assertArrayEquals(b, buffer);
byte[] expectedBytes = randomBytes(random);
byte[] actualBytes = input.readNBytes(expectedBytes.length);
assertArrayEquals(expectedBytes, actualBytes);
break;
}
}
Expand All @@ -107,19 +110,45 @@ protected InputStream openSlice(int slice) throws IOException {

}

private int readFully(InputStream stream, byte[] buffer) throws IOException {
for (int i = 0; i < buffer.length;) {
int read = stream.read(buffer, i, buffer.length - i);
if (read == -1) {
if (i == 0) {
return -1;
} else {
return i;
}
public void testReadZeroLength() throws IOException {
try (InputStream input = createSingleByteStream()) {
final byte[] buffer = new byte[100];
final int read = input.read(buffer, 0, 0);
MatcherAssert.assertThat(read, equalTo(0));
}
}

public void testInvalidOffsetAndLength() throws IOException {
try (InputStream input = createSingleByteStream()) {
final byte[] buffer = new byte[100];
expectThrows(NullPointerException.class, () -> input.read(null, 0, 10));
expectThrows(IndexOutOfBoundsException.class, () -> input.read(buffer, -1, 10));
expectThrows(IndexOutOfBoundsException.class, () -> input.read(buffer, 0, -1));
expectThrows(IndexOutOfBoundsException.class, () -> input.read(buffer, 0, buffer.length + 1));
}
}

public void testReadAllBytes() throws IOException {
final byte[] expectedResults = randomByteArrayOfLength(50_000);
final int numSlices = 200;
final int slizeSize = expectedResults.length / numSlices;

final List<byte[]> arraySlices = new ArrayList<>(numSlices);
for (int i = 0; i < numSlices; i++) {
final int offset = slizeSize * i;
arraySlices.add(Arrays.copyOfRange(expectedResults, offset, offset + slizeSize));
}
// Create a SlicedInputStream that will return the expected result in 2 slices
final byte[] actualResults;
try (InputStream is = new SlicedInputStream(numSlices) {
@Override
protected InputStream openSlice(int slice) {
return new ByteArrayInputStream(arraySlices.get(slice));
}
i += read;
}) {
actualResults = is.readAllBytes();
}
return buffer.length;
assertArrayEquals(expectedResults, actualResults);
}

private byte[] randomBytes(Random random) {
Expand All @@ -129,6 +158,15 @@ private byte[] randomBytes(Random random) {
return data;
}

private static InputStream createSingleByteStream() {
return new SlicedInputStream(1) {
@Override
protected InputStream openSlice(int slice) {
return new ByteArrayInputStream(new byte[] { 1 });
}
};
}

private static final class CheckClosedInputStream extends FilterInputStream {

public boolean closed = false;
Expand Down