Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: docker-regis...@packages.debian.org, z...@debian.org
Control: affects -1 + src:docker-registry

Please unblock package docker-registry

[ Reason ]
Upstream micro release for CVE-2023-2253 (Catalog API endpoint can lead to OOM
via malicious user input).

[ Impact ]
Fix security issue.

[ Tests ]
New unittest is added. The package has autopkgtest.

[ Risks ]

The debdiff contains some noise code style changes, otherwise they are trivial.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]
I attached a filtered debdiff, with following command,

 filterdiff --exclude '*/releases/*' --exclude '*/script/*' --exclude 
'*/.github/*' \
   --exclude '*.hcl'  --exclude '*.yml' --exclude '*/Dockerfile' \
   --exclude '*/Makefile' --exclude '*/.mailmap'  --exclude '*_test.go'

unblock docker-registry/2.8.2+ds1-1
diff -Nru -w docker-registry-2.8.1+ds1/configuration/configuration.go 
docker-registry-2.8.2+ds1/configuration/configuration.go
--- docker-registry-2.8.1+ds1/configuration/configuration.go    2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/configuration/configuration.go    2023-05-11 
18:11:57.000000000 +0800
@@ -194,6 +194,7 @@
        } `yaml:"redis,omitempty"`
 
        Health Health `yaml:"health,omitempty"`
+       Catalog Catalog `yaml:"catalog,omitempty"`
 
        Proxy Proxy `yaml:"proxy,omitempty"`
 
@@ -244,6 +245,16 @@
        } `yaml:"policy,omitempty"`
 }
 
+// Catalog is composed of MaxEntries.
+// Catalog endpoint (/v2/_catalog) configuration, it provides the configuration
+// options to control the maximum number of entries returned by the catalog 
endpoint.
+type Catalog struct {
+       // Max number of entries returned by the catalog endpoint. Requesting n 
entries
+       // to the catalog endpoint will return at most MaxEntries entries.
+       // An empty or a negative value will set a default of 1000 maximum 
entries by default.
+       MaxEntries int `yaml:"maxentries,omitempty"`
+}
+
 // LogHook is composed of hook Level and Type.
 // After hooks configuration, it can execute the next handling automatically,
 // when defined levels of log message emitted.
@@ -670,6 +681,11 @@
                                        if v0_1.Loglevel != Loglevel("") {
                                                v0_1.Loglevel = Loglevel("")
                                        }
+
+                                       if v0_1.Catalog.MaxEntries <= 0 {
+                                               v0_1.Catalog.MaxEntries = 1000
+                                       }
+
                                        if v0_1.Storage.Type() == "" {
                                                return nil, errors.New("no 
storage configuration provided")
                                        }
diff -Nru -w docker-registry-2.8.1+ds1/context/doc.go 
docker-registry-2.8.2+ds1/context/doc.go
--- docker-registry-2.8.1+ds1/context/doc.go    2022-03-09 01:52:36.000000000 
+0800
+++ docker-registry-2.8.2+ds1/context/doc.go    2023-05-11 18:11:57.000000000 
+0800
@@ -15,7 +15,7 @@
 // The above will store the version in the context and will be available to
 // the logger.
 //
-// Logging
+// # Logging
 //
 // The most useful aspect of this package is GetLogger. This function takes
 // any context.Context interface and returns the current logger from the
@@ -65,7 +65,7 @@
 // added to the request context, is unique to that context and can have
 // request scoped variables.
 //
-// HTTP Requests
+// # HTTP Requests
 //
 // This package also contains several methods for working with http requests.
 // The concepts are very similar to those described above. We simply place the
diff -Nru -w docker-registry-2.8.1+ds1/context/http.go 
docker-registry-2.8.2+ds1/context/http.go
--- docker-registry-2.8.1+ds1/context/http.go   2022-03-09 01:52:36.000000000 
+0800
+++ docker-registry-2.8.2+ds1/context/http.go   2023-05-11 18:11:57.000000000 
+0800
@@ -246,11 +246,7 @@
                        return ctx.vars
                }
 
-               if strings.HasPrefix(keyStr, "vars.") {
-                       keyStr = strings.TrimPrefix(keyStr, "vars.")
-               }
-
-               if v, ok := ctx.vars[keyStr]; ok {
+               if v, ok := ctx.vars[strings.TrimPrefix(keyStr, "vars.")]; ok {
                        return v
                }
        }
diff -Nru -w docker-registry-2.8.1+ds1/debian/changelog 
docker-registry-2.8.2+ds1/debian/changelog
--- docker-registry-2.8.1+ds1/debian/changelog  2022-06-29 20:32:34.000000000 
+0800
+++ docker-registry-2.8.2+ds1/debian/changelog  2023-05-13 23:21:12.000000000 
+0800
@@ -1,3 +1,14 @@
+docker-registry (2.8.2+ds1-1) unstable; urgency=medium
+
+  * Team upload
+  * New upstream version 2.8.2+ds1
+    + CVE-2023-2253: Catalog API endpoint can lead to OOM via malicious user
+      input (Closes: #1035956)
+  * Drop patch merged by upstream
+    + 0009-Fix-panic-in-inmemory-driver.patch
+
+ -- Shengjing Zhu <z...@debian.org>  Sat, 13 May 2023 23:21:12 +0800
+
 docker-registry (2.8.1+ds1-2) unstable; urgency=medium
 
   [ Debian Janitor ]
diff -Nru -w 
docker-registry-2.8.1+ds1/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch
 
docker-registry-2.8.2+ds1/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch
--- 
docker-registry-2.8.1+ds1/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch
    2022-06-29 20:32:34.000000000 +0800
+++ 
docker-registry-2.8.2+ds1/debian/patches/0007-Skip-TestRegistryAsCacheMutationAPIs.patch
    2023-05-13 23:21:12.000000000 +0800
@@ -12,10 +12,10 @@
  1 file changed, 1 insertion(+)
 
 diff --git a/registry/handlers/api_test.go b/registry/handlers/api_test.go
-index 2d3edc7..a07184b 100644
+index bf037d4..207e167 100644
 --- a/registry/handlers/api_test.go
 +++ b/registry/handlers/api_test.go
-@@ -2468,6 +2468,7 @@ func createRepository(env *testEnv, t *testing.T, 
imageName string, tag string)
+@@ -2728,6 +2728,7 @@ func createRepository(env *testEnv, t *testing.T, 
imageName string, tag string)
  // Test mutation operations on a registry configured as a cache.  Ensure that 
they return
  // appropriate errors.
  func TestRegistryAsCacheMutationAPIs(t *testing.T) {
diff -Nru -w 
docker-registry-2.8.1+ds1/debian/patches/0009-Fix-panic-in-inmemory-driver.patch
 
docker-registry-2.8.2+ds1/debian/patches/0009-Fix-panic-in-inmemory-driver.patch
--- 
docker-registry-2.8.1+ds1/debian/patches/0009-Fix-panic-in-inmemory-driver.patch
    2022-06-29 20:32:34.000000000 +0800
+++ 
docker-registry-2.8.2+ds1/debian/patches/0009-Fix-panic-in-inmemory-driver.patch
    1970-01-01 08:00:00.000000000 +0800
@@ -1,23 +0,0 @@
-From: Shengjing Zhu <z...@debian.org>
-Date: Sun, 27 Mar 2022 19:38:07 +0800
-Subject: Fix panic in inmemory driver
-
-Forwarded: https://github.com/distribution/distribution/pull/3615
----
- registry/storage/driver/inmemory/mfs.go | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/registry/storage/driver/inmemory/mfs.go 
b/registry/storage/driver/inmemory/mfs.go
-index 9a2865f..24eeef9 100644
---- a/registry/storage/driver/inmemory/mfs.go
-+++ b/registry/storage/driver/inmemory/mfs.go
-@@ -279,6 +279,9 @@ func (f *file) sectionReader(offset int64) io.Reader {
- }
- 
- func (f *file) ReadAt(p []byte, offset int64) (n int, err error) {
-+      if offset >= int64(len(f.data)) {
-+              return 0, io.EOF
-+      }
-       return copy(p, f.data[offset:]), nil
- }
- 
diff -Nru -w docker-registry-2.8.1+ds1/debian/patches/series 
docker-registry-2.8.2+ds1/debian/patches/series
--- docker-registry-2.8.1+ds1/debian/patches/series     2022-06-29 
20:32:34.000000000 +0800
+++ docker-registry-2.8.2+ds1/debian/patches/series     2023-05-13 
23:21:12.000000000 +0800
@@ -6,4 +6,3 @@
 0006-Skip-TestHTTPChecker.patch
 0007-Skip-TestRegistryAsCacheMutationAPIs.patch
 0008-Skip-flaky-TestGracefulShutdown-and-TestRegistrySupp.patch
-0009-Fix-panic-in-inmemory-driver.patch
diff -Nru -w docker-registry-2.8.1+ds1/.dockerignore 
docker-registry-2.8.2+ds1/.dockerignore
--- docker-registry-2.8.1+ds1/.dockerignore     1970-01-01 08:00:00.000000000 
+0800
+++ docker-registry-2.8.2+ds1/.dockerignore     2023-05-11 18:11:57.000000000 
+0800
@@ -0,0 +1 @@
+bin/
diff -Nru -w docker-registry-2.8.1+ds1/health/doc.go 
docker-registry-2.8.2+ds1/health/doc.go
--- docker-registry-2.8.1+ds1/health/doc.go     2022-03-09 01:52:36.000000000 
+0800
+++ docker-registry-2.8.2+ds1/health/doc.go     2023-05-11 18:11:57.000000000 
+0800
@@ -13,7 +13,7 @@
 // particularly useful for checks that verify upstream connectivity or
 // database status, since they might take a long time to return/timeout.
 //
-// Installing
+// # Installing
 //
 // To install health, just import it in your application:
 //
@@ -35,7 +35,7 @@
 // After importing these packages to your main application, you can start
 // registering checks.
 //
-// Registering Checks
+// # Registering Checks
 //
 // The recommended way of registering checks is using a periodic Check.
 // PeriodicChecks run on a certain schedule and asynchronously update the
@@ -84,7 +84,7 @@
 //   return Errors.new("This is an error!")
 //  }))
 //
-// Examples
+// # Examples
 //
 // You could also use the health checker mechanism to ensure your application
 // only comes up if certain conditions are met, or to allow the developer to
diff -Nru -w docker-registry-2.8.1+ds1/registry/api/v2/descriptors.go 
docker-registry-2.8.2+ds1/registry/api/v2/descriptors.go
--- docker-registry-2.8.1+ds1/registry/api/v2/descriptors.go    2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/api/v2/descriptors.go    2023-05-11 
18:11:57.000000000 +0800
@@ -134,6 +134,19 @@
                },
        }
 
+       invalidPaginationResponseDescriptor = ResponseDescriptor{
+               Name:        "Invalid pagination number",
+               Description: "The received parameter n was invalid in some way, 
as described by the error code. The client should resolve the issue and retry 
the request.",
+               StatusCode:  http.StatusBadRequest,
+               Body: BodyDescriptor{
+                       ContentType: "application/json",
+                       Format:      errorsBody,
+               },
+               ErrorCodes: []errcode.ErrorCode{
+                       ErrorCodePaginationNumberInvalid,
+               },
+       }
+
        repositoryNotFoundResponseDescriptor = ResponseDescriptor{
                Name:        "No Such Repository Error",
                StatusCode:  http.StatusNotFound,
@@ -490,6 +503,7 @@
                                                        },
                                                },
                                                Failures: []ResponseDescriptor{
+                                                       
invalidPaginationResponseDescriptor,
                                                        
unauthorizedResponseDescriptor,
                                                        
repositoryNotFoundResponseDescriptor,
                                                        
deniedResponseDescriptor,
@@ -1578,6 +1592,9 @@
                                                                },
                                                        },
                                                },
+                                               Failures: []ResponseDescriptor{
+                                                       
invalidPaginationResponseDescriptor,
+                                               },
                                        },
                                },
                        },
diff -Nru -w docker-registry-2.8.1+ds1/registry/api/v2/errors.go 
docker-registry-2.8.2+ds1/registry/api/v2/errors.go
--- docker-registry-2.8.1+ds1/registry/api/v2/errors.go 2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/api/v2/errors.go 2023-05-11 
18:11:57.000000000 +0800
@@ -133,4 +133,13 @@
                longer proceed.`,
                HTTPStatusCode: http.StatusNotFound,
        })
+
+       ErrorCodePaginationNumberInvalid = errcode.Register(errGroup, 
errcode.ErrorDescriptor{
+               Value:   "PAGINATION_NUMBER_INVALID",
+               Message: "invalid number of results requested",
+               Description: `Returned when the "n" parameter (number of results
+               to return) is not an integer, "n" is negative or "n" is bigger 
than
+               the maximum allowed.`,
+               HTTPStatusCode: http.StatusBadRequest,
+       })
 )
diff -Nru -w docker-registry-2.8.1+ds1/registry/auth/auth.go 
docker-registry-2.8.2+ds1/registry/auth/auth.go
--- docker-registry-2.8.1+ds1/registry/auth/auth.go     2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/auth/auth.go     2023-05-11 
18:11:57.000000000 +0800
@@ -29,7 +29,6 @@
 //                             }
 //                     }
 //             }
-//
 package auth
 
 import (
diff -Nru -w docker-registry-2.8.1+ds1/registry/auth/token/token.go 
docker-registry-2.8.2+ds1/registry/auth/token/token.go
--- docker-registry-2.8.1+ds1/registry/auth/token/token.go      2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/auth/token/token.go      2023-05-11 
18:11:57.000000000 +0800
@@ -185,6 +185,7 @@
 
 // VerifySigningKey attempts to get the key which was used to sign this token.
 // The token header should contain either of these 3 fields:
+//
 //      `x5c` - The x509 certificate chain for the signing key. Needs to be
 //              verified.
 //      `jwk` - The JSON Web Key representation of the signing key.
@@ -192,6 +193,7 @@
 //      `kid` - The unique identifier for the key. This library interprets it
 //              as a libtrust fingerprint. The key itself can be looked up in
 //              the trustedKeys field of the given verify options.
+//
 // Each of these methods are tried in that order of preference until the
 // signing key is found or an error is returned.
 func (t *Token) VerifySigningKey(verifyOpts VerifyOptions) (signingKey 
libtrust.PublicKey, err error) {
diff -Nru -w docker-registry-2.8.1+ds1/registry/client/errors.go 
docker-registry-2.8.2+ds1/registry/client/errors.go
--- docker-registry-2.8.1+ds1/registry/client/errors.go 2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/client/errors.go 2023-05-11 
18:11:57.000000000 +0800
@@ -55,6 +55,8 @@
                switch statusCode {
                case http.StatusUnauthorized:
                        return 
errcode.ErrorCodeUnauthorized.WithMessage(detailsErr.Details)
+               case http.StatusForbidden:
+                       return 
errcode.ErrorCodeDenied.WithMessage(detailsErr.Details)
                case http.StatusTooManyRequests:
                        return 
errcode.ErrorCodeTooManyRequests.WithMessage(detailsErr.Details)
                default:
diff -Nru -w docker-registry-2.8.1+ds1/registry/client/repository.go 
docker-registry-2.8.2+ds1/registry/client/repository.go
--- docker-registry-2.8.1+ds1/registry/client/repository.go     2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/client/repository.go     2023-05-11 
18:11:57.000000000 +0800
@@ -114,9 +114,7 @@
                        return 0, err
                }
 
-               for cnt := range ctlg.Repositories {
-                       entries[cnt] = ctlg.Repositories[cnt]
-               }
+               copy(entries, ctlg.Repositories)
                numFilled = len(ctlg.Repositories)
 
                link := resp.Header.Get("Link")
diff -Nru -w docker-registry-2.8.1+ds1/registry/client/transport/http_reader.go 
docker-registry-2.8.2+ds1/registry/client/transport/http_reader.go
--- docker-registry-2.8.1+ds1/registry/client/transport/http_reader.go  
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/client/transport/http_reader.go  
2023-05-11 18:11:57.000000000 +0800
@@ -180,7 +180,6 @@
                // context.GetLogger(hrs.context).Infof("Range: %s", 
req.Header.Get("Range"))
        }
 
-       req.Header.Add("Accept-Encoding", "identity")
        resp, err := hrs.client.Do(req)
        if err != nil {
                return nil, err
diff -Nru -w docker-registry-2.8.1+ds1/registry/handlers/basicauth.go 
docker-registry-2.8.2+ds1/registry/handlers/basicauth.go
--- docker-registry-2.8.1+ds1/registry/handlers/basicauth.go    2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/handlers/basicauth.go    2023-05-11 
18:11:57.000000000 +0800
@@ -1,3 +1,4 @@
+//go:build go1.4
 // +build go1.4
 
 package handlers
diff -Nru -w docker-registry-2.8.1+ds1/registry/handlers/basicauth_prego14.go 
docker-registry-2.8.2+ds1/registry/handlers/basicauth_prego14.go
--- docker-registry-2.8.1+ds1/registry/handlers/basicauth_prego14.go    
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/handlers/basicauth_prego14.go    
2023-05-11 18:11:57.000000000 +0800
@@ -1,3 +1,4 @@
+//go:build !go1.4
 // +build !go1.4
 
 package handlers
diff -Nru -w docker-registry-2.8.1+ds1/registry/handlers/catalog.go 
docker-registry-2.8.2+ds1/registry/handlers/catalog.go
--- docker-registry-2.8.1+ds1/registry/handlers/catalog.go      2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/handlers/catalog.go      2023-05-11 
18:11:57.000000000 +0800
@@ -9,11 +9,13 @@
        "strconv"
 
        "github.com/docker/distribution/registry/api/errcode"
+       v2 "github.com/docker/distribution/registry/api/v2"
        "github.com/docker/distribution/registry/storage/driver"
+
        "github.com/gorilla/handlers"
 )
 
-const maximumReturnedEntries = 100
+const defaultReturnedEntries = 100
 
 func catalogDispatcher(ctx *Context, r *http.Request) http.Handler {
        catalogHandler := &catalogHandler{
@@ -38,29 +40,55 @@
 
        q := r.URL.Query()
        lastEntry := q.Get("last")
-       maxEntries, err := strconv.Atoi(q.Get("n"))
-       if err != nil || maxEntries < 0 {
-               maxEntries = maximumReturnedEntries
+
+       entries := defaultReturnedEntries
+       maximumConfiguredEntries := ch.App.Config.Catalog.MaxEntries
+
+       // parse n, if n unparseable, or negative assign it to 
defaultReturnedEntries
+       if n := q.Get("n"); n != "" {
+               parsedMax, err := strconv.Atoi(n)
+               if err == nil {
+                       if parsedMax > maximumConfiguredEntries {
+                               ch.Errors = append(ch.Errors, 
v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]int{"n": parsedMax}))
+                               return
+                       } else if parsedMax >= 0 {
+                               entries = parsedMax
+                       }
+               }
        }
 
-       repos := make([]string, maxEntries)
+       // then enforce entries to be between 0 & maximumConfiguredEntries
+       // max(0, min(entries, maximumConfiguredEntries))
+       if entries < 0 || entries > maximumConfiguredEntries {
+               entries = maximumConfiguredEntries
+       }
 
-       filled, err := ch.App.registry.Repositories(ch.Context, repos, 
lastEntry)
-       _, pathNotFound := err.(driver.PathNotFoundError)
+       repos := make([]string, entries)
+       filled := 0
 
-       if err == io.EOF || pathNotFound {
+       // entries is guaranteed to be >= 0 and < maximumConfiguredEntries
+       if entries == 0 {
                moreEntries = false
-       } else if err != nil {
+       } else {
+               returnedRepositories, err := 
ch.App.registry.Repositories(ch.Context, repos, lastEntry)
+               if err != nil {
+                       _, pathNotFound := err.(driver.PathNotFoundError)
+                       if err != io.EOF && !pathNotFound {
                ch.Errors = append(ch.Errors, 
errcode.ErrorCodeUnknown.WithDetail(err))
                return
        }
+                       // err is either io.EOF or not PathNotFoundError
+                       moreEntries = false
+               }
+               filled = returnedRepositories
+       }
 
        w.Header().Set("Content-Type", "application/json; charset=utf-8")
 
        // Add a link header if there are more entries to retrieve
        if moreEntries {
-               lastEntry = repos[len(repos)-1]
-               urlStr, err := createLinkEntry(r.URL.String(), maxEntries, 
lastEntry)
+               lastEntry = repos[filled-1]
+               urlStr, err := createLinkEntry(r.URL.String(), entries, 
lastEntry)
                if err != nil {
                        ch.Errors = append(ch.Errors, 
errcode.ErrorCodeUnknown.WithDetail(err))
                        return
diff -Nru -w 
docker-registry-2.8.1+ds1/registry/storage/blobwriter_nonresumable.go 
docker-registry-2.8.2+ds1/registry/storage/blobwriter_nonresumable.go
--- docker-registry-2.8.1+ds1/registry/storage/blobwriter_nonresumable.go       
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/storage/blobwriter_nonresumable.go       
2023-05-11 18:11:57.000000000 +0800
@@ -1,3 +1,4 @@
+//go:build noresumabledigest
 // +build noresumabledigest
 
 package storage
diff -Nru -w docker-registry-2.8.1+ds1/registry/storage/blobwriter_resumable.go 
docker-registry-2.8.2+ds1/registry/storage/blobwriter_resumable.go
--- docker-registry-2.8.1+ds1/registry/storage/blobwriter_resumable.go  
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/storage/blobwriter_resumable.go  
2023-05-11 18:11:57.000000000 +0800
@@ -1,3 +1,4 @@
+//go:build !noresumabledigest
 // +build !noresumabledigest
 
 package storage
diff -Nru -w docker-registry-2.8.1+ds1/registry/storage/driver/gcs/gcs.go 
docker-registry-2.8.2+ds1/registry/storage/driver/gcs/gcs.go
--- docker-registry-2.8.1+ds1/registry/storage/driver/gcs/gcs.go        
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/storage/driver/gcs/gcs.go        
2023-05-11 18:11:57.000000000 +0800
@@ -10,6 +10,7 @@
 // Note that the contents of incomplete uploads are not accessible even though
 // Stat returns their length
 //
+//go:build include_gcs
 // +build include_gcs
 
 package gcs
diff -Nru -w docker-registry-2.8.1+ds1/registry/storage/driver/inmemory/mfs.go 
docker-registry-2.8.2+ds1/registry/storage/driver/inmemory/mfs.go
--- docker-registry-2.8.1+ds1/registry/storage/driver/inmemory/mfs.go   
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/storage/driver/inmemory/mfs.go   
2023-05-11 18:11:57.000000000 +0800
@@ -279,6 +279,9 @@
 }
 
 func (f *file) ReadAt(p []byte, offset int64) (n int, err error) {
+       if offset >= int64(len(f.data)) {
+               return 0, io.EOF
+       }
        return copy(p, f.data[offset:]), nil
 }
 
diff -Nru -w 
docker-registry-2.8.1+ds1/registry/storage/driver/middleware/cloudfront/middleware.go
 
docker-registry-2.8.2+ds1/registry/storage/driver/middleware/cloudfront/middleware.go
--- 
docker-registry-2.8.1+ds1/registry/storage/driver/middleware/cloudfront/middleware.go
       2022-03-09 01:52:36.000000000 +0800
+++ 
docker-registry-2.8.2+ds1/registry/storage/driver/middleware/cloudfront/middleware.go
       2023-05-11 18:11:57.000000000 +0800
@@ -1,6 +1,5 @@
 // Package middleware - cloudfront wrapper for storage libs
 // N.B. currently only works with S3, not arbitrary sites
-//
 package middleware
 
 import (
@@ -38,7 +37,9 @@
 
 // Optional options: ipFilteredBy, awsregion
 // ipfilteredby: valid value "none|aws|awsregion". "none", do not filter any 
IP, default value. "aws", only aws IP goes
+//
 //               to S3 directly. "awsregion", only regions listed in awsregion 
options goes to S3 directly
+//
 // awsregion: a comma separated string of AWS regions.
 func newCloudFrontStorageMiddleware(storageDriver storagedriver.StorageDriver, 
options map[string]interface{}) (storagedriver.StorageDriver, error) {
        // parse baseurl
diff -Nru -w docker-registry-2.8.1+ds1/registry/storage/driver/oss/oss.go 
docker-registry-2.8.2+ds1/registry/storage/driver/oss/oss.go
--- docker-registry-2.8.1+ds1/registry/storage/driver/oss/oss.go        
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/storage/driver/oss/oss.go        
2023-05-11 18:11:57.000000000 +0800
@@ -7,6 +7,7 @@
 // Because OSS is a key, value store the Stat call does not support last 
modification
 // time for directories (directories are an abstraction for key, value stores)
 //
+//go:build include_oss
 // +build include_oss
 
 package oss
diff -Nru -w docker-registry-2.8.1+ds1/registry/storage/driver/s3-aws/s3.go 
docker-registry-2.8.2+ds1/registry/storage/driver/s3-aws/s3.go
--- docker-registry-2.8.1+ds1/registry/storage/driver/s3-aws/s3.go      
2022-03-09 01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/storage/driver/s3-aws/s3.go      
2023-05-11 18:11:57.000000000 +0800
@@ -549,9 +549,9 @@
 
 // Writer returns a FileWriter which will store the content written to it
 // at the location designated by "path" after the call to Commit.
-func (d *driver) Writer(ctx context.Context, path string, append bool) 
(storagedriver.FileWriter, error) {
+func (d *driver) Writer(ctx context.Context, path string, appendParam bool) 
(storagedriver.FileWriter, error) {
        key := d.s3Path(path)
-       if !append {
+       if !appendParam {
                // TODO (brianbland): cancel other uploads at this path
                resp, err := 
d.S3.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
                        Bucket:               aws.String(d.Bucket),
@@ -574,7 +574,7 @@
        if err != nil {
                return nil, parseError(path, err)
        }
-
+       var allParts []*s3.Part
        for _, multi := range resp.Uploads {
                if key != *multi.Key {
                        continue
@@ -587,11 +587,20 @@
                if err != nil {
                        return nil, parseError(path, err)
                }
-               var multiSize int64
-               for _, part := range resp.Parts {
-                       multiSize += *part.Size
+               allParts = append(allParts, resp.Parts...)
+               for *resp.IsTruncated {
+                       resp, err = d.S3.ListParts(&s3.ListPartsInput{
+                               Bucket:           aws.String(d.Bucket),
+                               Key:              aws.String(key),
+                               UploadId:         multi.UploadId,
+                               PartNumberMarker: resp.NextPartNumberMarker,
+                       })
+                       if err != nil {
+                               return nil, parseError(path, err)
+                       }
+                       allParts = append(allParts, resp.Parts...)
                }
-               return d.newWriter(key, *multi.UploadId, resp.Parts), nil
+               return d.newWriter(key, *multi.UploadId, allParts), nil
        }
        return nil, storagedriver.PathNotFoundError{Path: path}
 }
diff -Nru -w docker-registry-2.8.1+ds1/registry/storage/paths.go 
docker-registry-2.8.2+ds1/registry/storage/paths.go
--- docker-registry-2.8.1+ds1/registry/storage/paths.go 2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/registry/storage/paths.go 2023-05-11 
18:11:57.000000000 +0800
@@ -435,7 +435,6 @@
 // groups of digest folder. It will be as follows:
 //
 //     <algorithm>/<first two bytes of digest>/<full digest>
-//
 func digestPathComponents(dgst digest.Digest, multilevel bool) ([]string, 
error) {
        if err := dgst.Validate(); err != nil {
                return nil, err
diff -Nru -w docker-registry-2.8.1+ds1/version/print.go 
docker-registry-2.8.2+ds1/version/print.go
--- docker-registry-2.8.1+ds1/version/print.go  2022-03-09 01:52:36.000000000 
+0800
+++ docker-registry-2.8.2+ds1/version/print.go  2023-05-11 18:11:57.000000000 
+0800
@@ -15,7 +15,6 @@
 // with version "v2.0" would print the following:
 //
 //     registry github.com/docker/distribution v2.0
-//
 func FprintVersion(w io.Writer) {
        fmt.Fprintln(w, os.Args[0], Package, Version)
 }
diff -Nru -w docker-registry-2.8.1+ds1/version/version.go 
docker-registry-2.8.2+ds1/version/version.go
--- docker-registry-2.8.1+ds1/version/version.go        2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/version/version.go        2023-05-11 
18:11:57.000000000 +0800
@@ -8,7 +8,7 @@
 // the latest release tag by hand, always suffixed by "+unknown". During
 // build, it will be replaced by the actual version. The value here will be
 // used if the registry is run after a go get based install.
-var Version = "v2.8.1+unknown"
+var Version = "v2.8.2+unknown"
 
 // Revision is filled with the VCS (e.g. git) revision being used to build
 // the program at linking time.
diff -Nru -w docker-registry-2.8.1+ds1/version/version.sh 
docker-registry-2.8.2+ds1/version/version.sh
--- docker-registry-2.8.1+ds1/version/version.sh        2022-03-09 
01:52:36.000000000 +0800
+++ docker-registry-2.8.2+ds1/version/version.sh        2023-05-11 
18:11:57.000000000 +0800
@@ -17,7 +17,7 @@
 // Version indicates which version of the binary is running. This is set to
 // the latest release tag by hand, always suffixed by "+unknown". During
 // build, it will be replaced by the actual version. The value here will be
-// used if the registry is run after a go get based install.
+// used if the registry is run after a go install based install.
 var Version = "$(git describe --match 'v[0-9]*' --dirty='.m' --always)+unknown"
 
 // Revision is filled with the VCS (e.g. git) revision being used to build

Reply via email to