Skip to content

Commit 60a96ac

Browse files
dgrrjasdel
authored andcommitted
service/s3/s3manager: Fix index out of range when a io.Reader returns -1 (#378)
Fixes the S3 Upload Manager's handling of an unbounded streaming reader that returns negative bytes read.
1 parent 57d74d6 commit 60a96ac

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

CHANGELOG_PENDING.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Deprecations
1010
* Removes support for deprecated Go versions ([#393](https://github.com/aws/aws-sdk-go-v2/pull/393))
1111
* Removes support for Go version specific files from the SDK. Also removes irrelevant build tags, and updates the README.md file.
1212
* Raises the minimum supported version to Go 1.11 for the SDK. Older versions may work, but are not actively supported
13-
13+
1414
SDK Features
1515
---
1616

@@ -21,6 +21,8 @@ SDK Enhancements
2121
* Related to [aws/aws-sdk-go#2310](https://github.com/aws/aws-sdk-go/pull/2310)
2222
* Fixes [#251](https://github.com/aws/aws-sdk-go-v2/issues/251)
2323
* `aws/request` : Retryer is now a named field on Request. ([#393](https://github.com/aws/aws-sdk-go-v2/pull/393))
24-
24+
2525
SDK Bugs
2626
---
27+
* `service/s3/s3manager`: Fix index out of range when a streaming reader returns -1 ([#378](https://github.com/aws/aws-sdk-go-v2/pull/378))
28+
* Fixes the S3 Upload Manager's handling of an unbounded streaming reader that returns negative bytes read.

service/s3/s3manager/upload.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,14 +445,22 @@ func (u *uploader) nextReader() (io.ReadSeeker, int, error) {
445445
default:
446446
part := make([]byte, u.cfg.PartSize)
447447
n, err := readFillBuf(r, part)
448+
if n < 0 {
449+
if err == nil {
450+
err = fmt.Errorf(
451+
"unable to read part, got negative bytes read(%d) without error, %v",
452+
n, err)
453+
}
454+
return nil, n, err
455+
}
448456
u.readerPos += int64(n)
449457

450458
return bytes.NewReader(part[0:n]), n, err
451459
}
452460
}
453461

454462
func readFillBuf(r io.Reader, b []byte) (offset int, err error) {
455-
for offset < len(b) && err == nil {
463+
for offset >= 0 && offset < len(b) && err == nil {
456464
var n int
457465
n, err = r.Read(b[offset:])
458466
offset += n

service/s3/s3manager/upload_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,35 @@ func TestUploadFailIfPartSizeTooSmall(t *testing.T) {
277277
}
278278
}
279279

280+
type negativeReader struct {
281+
}
282+
283+
func (nr *negativeReader) Read(_ []byte) (int, error) {
284+
return -1, io.ErrUnexpectedEOF
285+
}
286+
287+
func TestUploadReaderReturnsNegative(t *testing.T) {
288+
s, _, _ := loggingSvc(emptyList)
289+
mgr := s3manager.NewUploaderWithClient(s, func(u *s3manager.Uploader) {
290+
u.Concurrency = 1
291+
})
292+
293+
// should not panic
294+
_, err := mgr.Upload(&s3manager.UploadInput{
295+
Bucket: aws.String("Bucket"),
296+
Key: aws.String("Key"),
297+
Body: &negativeReader{},
298+
})
299+
if err == nil {
300+
t.Error("Expected error, but received none")
301+
}
302+
303+
aerr := err.(awserr.Error)
304+
if aerr.OrigErr() != io.ErrUnexpectedEOF {
305+
t.Fatalf("expected %s. Got %s", io.ErrUnexpectedEOF, aerr.OrigErr())
306+
}
307+
}
308+
280309
func TestUploadOrderSingle(t *testing.T) {
281310
s, ops, args := loggingSvc(emptyList)
282311
mgr := s3manager.NewUploaderWithClient(s)

0 commit comments

Comments
 (0)