mirror of
https://github.com/versity/versitygw.git
synced 2026-09-18 22:14:24 +00:00
fix: adds validation for chunk sizes in unsigned streaming trailer upload
Fixes #1665 S3 enforces a validation rule for unsigned streaming payload trailer uploads: all chunk sizes must be greater than 8192 bytes except for the final chunk. This fix adds a check in the unsigned chunk reader that validates chunk sizes by comparing each chunk size to the previous one.
This commit is contained in:
@@ -35,8 +35,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
trailerDelim = []byte{'\n', '\r', '\n'}
|
||||
errMalformedEncoding = errors.New("malformed chunk encoding")
|
||||
trailerDelim = []byte{'\n', '\r', '\n'}
|
||||
minChunkSize int64 = 8192
|
||||
errMalformedEncoding = errors.New("malformed chunk encoding")
|
||||
)
|
||||
|
||||
type UnsignedChunkReader struct {
|
||||
@@ -46,6 +47,9 @@ type UnsignedChunkReader struct {
|
||||
hasher hash.Hash
|
||||
stash []byte
|
||||
offset int
|
||||
// this data is necessary for 'InvalidChunkSizeError' error
|
||||
// TODO: add 'Chunk' and 'BadChunkSize' in the error
|
||||
chunkSizes []int64
|
||||
}
|
||||
|
||||
func NewUnsignedChunkReader(r io.Reader, ct checksumType) (*UnsignedChunkReader, error) {
|
||||
@@ -65,6 +69,7 @@ func NewUnsignedChunkReader(r io.Reader, ct checksumType) (*UnsignedChunkReader,
|
||||
checksumType: ct,
|
||||
stash: make([]byte, 0),
|
||||
hasher: hasher,
|
||||
chunkSizes: []int64{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -188,11 +193,36 @@ func (ucr *UnsignedChunkReader) extractChunkSize() (int64, error) {
|
||||
return 0, s3err.GetAPIError(s3err.ErrIncompleteBody)
|
||||
}
|
||||
|
||||
if !ucr.isValidChunkSize(chunkSize) {
|
||||
return chunkSize, s3err.GetAPIError(s3err.ErrInvalidChunkSize)
|
||||
}
|
||||
|
||||
ucr.chunkSizes = append(ucr.chunkSizes, chunkSize)
|
||||
|
||||
debuglogger.Infof("chunk size extracted: %v", chunkSize)
|
||||
|
||||
return chunkSize, nil
|
||||
}
|
||||
|
||||
// isValidChunkSize checks if the parsed chunk size is valid
|
||||
// they follow one rule: all chunk sizes except for the last one
|
||||
// should be greater than 8192
|
||||
func (ucr *UnsignedChunkReader) isValidChunkSize(size int64) bool {
|
||||
if len(ucr.chunkSizes) == 0 {
|
||||
// any valid number is valid as a first chunk size
|
||||
return true
|
||||
}
|
||||
|
||||
lastChunkSize := ucr.chunkSizes[len(ucr.chunkSizes)-1]
|
||||
// any chunk size, except the last one should be greater than 8192
|
||||
if size != 0 && lastChunkSize < minChunkSize {
|
||||
debuglogger.Logf("invalid chunk size %v", lastChunkSize)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Reads and validates the trailer at the end
|
||||
func (ucr *UnsignedChunkReader) readTrailer() error {
|
||||
var trailerBuffer bytes.Buffer
|
||||
|
||||
Reference in New Issue
Block a user