Skip to content

Commit 4055f1f

Browse files
droazenmichaelbausor
authored andcommitted
google-cloud-nio: CloudStorageReadChannel: fix channel position overflow (#2283)
This fixes a critical bug in CloudStorageReadChannel in which the channel position (a long) was getting down-cast to int in CloudStorageReadChannel.innerOpen(). This could cause the channel position to become negative or a wildly incorrect positive value if the channel position was greater than MAX_INT. In practice, this bug would only manifest itself if the channel was constructed with a non-zero initial position, or if the channel was reopened in response to an error. Included a test case that fails without the fix, and passes with the fix.
1 parent 10bc8bb commit 4055f1f

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

google-cloud-contrib/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/CloudStorageReadChannel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ private CloudStorageReadChannel(Storage gcsStorage, BlobId file, long position,
8282
private void innerOpen() throws IOException {
8383
this.channel = gcsStorage.reader(file);
8484
if (position > 0) {
85-
channel.seek((int) position);
85+
channel.seek(position);
8686
}
8787
}
8888

google-cloud-contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/CloudStorageReadChannelTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.junit.rules.ExpectedException;
3838
import org.junit.runner.RunWith;
3939
import org.junit.runners.JUnit4;
40+
import org.mockito.ArgumentCaptor;
4041

4142
import javax.net.ssl.SSLHandshakeException;
4243
import java.io.IOException;
@@ -191,4 +192,25 @@ public void testSetPosition() throws IOException {
191192
verify(gcsChannel).seek(1);
192193
verify(gcsChannel, times(5)).isOpen();
193194
}
195+
196+
/*
197+
* This test case was crafted in response to a bug in CloudStorageReadChannel in which the
198+
* channel position (a long) was getting truncated to an int when seeking on the encapsulated
199+
* ReadChannel in innerOpen(). This test case fails when the bad long -> int cast is present,
200+
* and passes when it's removed.
201+
*/
202+
@Test
203+
public void testChannelPositionDoesNotGetTruncatedToInt() throws IOException {
204+
// This position value will overflow to a negative value if a long -> int cast is attempted
205+
long startPosition = 11918483280L;
206+
ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class);
207+
208+
// Invoke CloudStorageReadChannel.create() to trigger a call to the private
209+
// CloudStorageReadChannel.innerOpen() method, which does a seek on our gcsChannel.
210+
CloudStorageReadChannel.create(gcsStorage, file, startPosition, 1);
211+
212+
// Confirm that our position did not overflow during the seek in CloudStorageReadChannel.innerOpen()
213+
verify(gcsChannel).seek(captor.capture());
214+
assertThat(captor.getValue()).isEqualTo(startPosition);
215+
}
194216
}

0 commit comments

Comments
 (0)