Skip to content

Commit eb3f3e6

Browse files
authored
Preserve content-length when calling mark in SdkLengthAwareInputStream (#6408)
* Preserve content-length when calling mark in SdkLengthAwareInputStream * Add test case * Ensure that markedRemaining is initialized
1 parent b3fe008 commit eb3f3e6

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Preserve the initial content-length when calling mark in SdkLengthAwareInputStream."
6+
}

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStream.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@
3232
@SdkInternalApi
3333
public class SdkLengthAwareInputStream extends FilterInputStream {
3434
private static final Logger LOG = Logger.loggerFor(SdkLengthAwareInputStream.class);
35-
private long length;
35+
private final long length;
3636
private long remaining;
37+
private long markedRemaining;
3738

3839
public SdkLengthAwareInputStream(InputStream in, long length) {
3940
super(in);
4041
this.length = Validate.isNotNegative(length, "length");
4142
this.remaining = this.length;
43+
this.markedRemaining = this.remaining;
4244
}
4345

4446
@Override
@@ -104,15 +106,14 @@ public int available() throws IOException {
104106
@Override
105107
public void mark(int readlimit) {
106108
super.mark(readlimit);
107-
// mark() causes reset() to change the stream's position back to the current position. Therefore, when reset() is called,
108-
// the new length of the stream will be equal to the current value of 'remaining'.
109-
length = remaining;
109+
// Store the current remaining bytes to restore on reset()
110+
markedRemaining = remaining;
110111
}
111112

112113
@Override
113114
public void reset() throws IOException {
114115
super.reset();
115-
remaining = length;
116+
remaining = markedRemaining;
116117
}
117118

118119
public long remaining() {

core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/io/SdkLengthAwareInputStreamTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,27 @@ void readByte_readExactLength_doesNotThrow() throws IOException {
249249
assertThat(total).isEqualTo(delegateLength);
250250
}
251251

252+
@Test
253+
void readBytePartialThenMark_doesNotResetContentLength() throws IOException {
254+
int delegateLength = 16;
255+
int expectedContentLength = delegateLength + 1;
256+
ByteArrayInputStream delegate = new ByteArrayInputStream(new byte[delegateLength]);
257+
258+
SdkLengthAwareInputStream is = new SdkLengthAwareInputStream(delegate, expectedContentLength);
259+
is.read(); // read one byte
260+
is.mark(1024);
261+
// read another byte and reset, the length should not be reset based on the byte that was already read
262+
is.read();
263+
is.reset();
264+
assertThatThrownBy(() -> {
265+
int read;
266+
while ((read = is.read()) != -1) {
267+
}
268+
})
269+
.isInstanceOf(IllegalStateException.class)
270+
.hasMessageContaining("The request content has fewer bytes than the specified content-length: " + expectedContentLength);
271+
}
272+
252273
@Test
253274
void readByte_delegateLongerThanRequired_truncated() throws IOException {
254275
int delegateLength = 32;

0 commit comments

Comments
 (0)