X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/26411493537eeb54ddafa2e9e29a5723edcd0316..387d86217ab0f119285c12735a6d0f3e606c23a1:/services/keepstore/keepstore.go diff --git a/services/keepstore/keepstore.go b/services/keepstore/keepstore.go index d85961fd2a..60d062e1e3 100644 --- a/services/keepstore/keepstore.go +++ b/services/keepstore/keepstore.go @@ -322,7 +322,10 @@ func (ks *keepstore) blockReadRemote(ctx context.Context, opts arvados.BlockRead } var remoteClient *keepclient.KeepClient var parts []string - var size int + li, err := getLocatorInfo(opts.Locator) + if err != nil { + return 0, err + } for i, part := range strings.Split(opts.Locator, "+") { switch { case i == 0: @@ -344,8 +347,6 @@ func (ks *keepstore) blockReadRemote(ctx context.Context, opts arvados.BlockRead } remoteClient = kc part = "A" + part[7:] - case len(part) > 0 && part[0] >= '0' && part[0] <= '9': - size, _ = strconv.Atoi(part) } parts = append(parts, part) } @@ -356,8 +357,8 @@ func (ks *keepstore) blockReadRemote(ctx context.Context, opts arvados.BlockRead if opts.LocalLocator == nil { // Read from remote cluster and stream response back // to caller - if rw, ok := opts.WriteTo.(http.ResponseWriter); ok && size > 0 { - rw.Header().Set("Content-Length", fmt.Sprintf("%d", size)) + if rw, ok := opts.WriteTo.(http.ResponseWriter); ok && li.size > 0 { + rw.Header().Set("Content-Length", fmt.Sprintf("%d", li.size)) } return remoteClient.BlockRead(ctx, arvados.BlockReadOptions{ Locator: locator, @@ -719,31 +720,44 @@ type locatorInfo struct { func getLocatorInfo(loc string) (locatorInfo, error) { var li locatorInfo - for i, part := range strings.Split(loc, "+") { - if i == 0 { - if len(part) != 32 { + plus := 0 // number of '+' chars seen so far + partlen := 0 // chars since last '+' + for i, c := range loc + "+" { + if c == '+' { + if partlen == 0 { + // double/leading/trailing '+' return li, errInvalidLocator } - li.hash = part + if plus == 0 { + if i != 32 { + return li, errInvalidLocator + } + li.hash = loc[:i] + } + if plus == 1 { + if size, err := strconv.Atoi(loc[i-partlen : i]); err == nil { + li.size = size + } + } + plus++ + partlen = 0 continue } - if i == 1 { - if size, err := strconv.Atoi(part); err == nil { - li.size = size - continue + partlen++ + if partlen == 1 { + if c == 'A' { + li.signed = true + } + if c == 'R' { + li.remote = true + } + if plus > 1 && c >= '0' && c <= '9' { + // size, if present at all, must come first + return li, errInvalidLocator } } - if len(part) == 0 { - return li, errInvalidLocator - } - if part[0] == 'A' { - li.signed = true - } - if part[0] == 'R' { - li.remote = true - } - if part[0] >= '0' && part[0] <= '9' { - // size, if present at all, must come first + if plus == 0 && !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) { + // non-hexadecimal char in hash part return li, errInvalidLocator } }