forked from TrueCloudLab/distribution
[Client] Fix error in parsing of 'Range' header.
* Result of regexp.FindStringSubmatch must be checked to be not nil. Otherwise it leads to `index out of range`. * Range header regexp is compiled only once to speedup (5x) the header parsing. Signed-off-by: Anton Tiurin <noxiouz@yandex.ru>
This commit is contained in:
parent
e492579718
commit
9c0519c4ed
2 changed files with 43 additions and 5 deletions
|
@ -67,6 +67,10 @@ type Client interface {
|
||||||
CancelBlobUpload(location string) error
|
CancelBlobUpload(location string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
patternRangeHeader = regexp.MustCompile("bytes=0-(\\d+)/(\\d+)")
|
||||||
|
)
|
||||||
|
|
||||||
// New returns a new Client which operates against a registry with the
|
// New returns a new Client which operates against a registry with the
|
||||||
// given base endpoint
|
// given base endpoint
|
||||||
// This endpoint should not include /v2/ or any part of the url after this.
|
// This endpoint should not include /v2/ or any part of the url after this.
|
||||||
|
@ -553,15 +557,18 @@ func (r *clientImpl) CancelBlobUpload(location string) error {
|
||||||
// parseRangeHeader parses out the offset and length from a returned Range
|
// parseRangeHeader parses out the offset and length from a returned Range
|
||||||
// header
|
// header
|
||||||
func parseRangeHeader(byteRangeHeader string) (int, int, error) {
|
func parseRangeHeader(byteRangeHeader string) (int, int, error) {
|
||||||
r := regexp.MustCompile("bytes=0-(\\d+)/(\\d+)")
|
submatches := patternRangeHeader.FindStringSubmatch(byteRangeHeader)
|
||||||
submatches := r.FindStringSubmatch(byteRangeHeader)
|
if submatches == nil || len(submatches) < 3 {
|
||||||
offset, err := strconv.ParseInt(submatches[1], 10, 0)
|
return 0, 0, fmt.Errorf("Malformed Range header")
|
||||||
|
}
|
||||||
|
|
||||||
|
offset, err := strconv.Atoi(submatches[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
length, err := strconv.ParseInt(submatches[2], 10, 0)
|
length, err := strconv.Atoi(submatches[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
return int(offset), int(length), nil
|
return offset, length, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,37 @@ type testBlob struct {
|
||||||
contents []byte
|
contents []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRangeHeaderParser(t *testing.T) {
|
||||||
|
const (
|
||||||
|
malformedRangeHeader = "bytes=0-A/C"
|
||||||
|
emptyRangeHeader = ""
|
||||||
|
rFirst = 100
|
||||||
|
rSecond = 200
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
wellformedRangeHeader = fmt.Sprintf("bytes=0-%d/%d", rFirst, rSecond)
|
||||||
|
)
|
||||||
|
|
||||||
|
if _, _, err := parseRangeHeader(malformedRangeHeader); err == nil {
|
||||||
|
t.Fatalf("malformedRangeHeader: error expected, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, _, err := parseRangeHeader(emptyRangeHeader); err == nil {
|
||||||
|
t.Fatalf("emptyRangeHeader: error expected, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
first, second, err := parseRangeHeader(wellformedRangeHeader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("wellformedRangeHeader: unexpected error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if first != rFirst || second != rSecond {
|
||||||
|
t.Fatalf("Range has been parsed unproperly: %d/%d", first, second)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestPush(t *testing.T) {
|
func TestPush(t *testing.T) {
|
||||||
name := "hello/world"
|
name := "hello/world"
|
||||||
tag := "sometag"
|
tag := "sometag"
|
||||||
|
|
Loading…
Reference in a new issue