Skip to content

Commit f55806a

Browse files
committed
fix(remote): wrap content.ErrMismatchedDigest on a Docker-Content-Digest mismatch
verifyContentDigest and (*manifestStore).generateDescriptor reported a response digest mismatch with a bare fmt.Errorf, so errors.Is could not classify it as content.ErrMismatchedDigest even though it is exactly the failure that sentinel names. ReadAll() already wrapped it, so whether a caller could classify "the registry served the wrong bytes" depended on which layer caught it. Wrap content.ErrMismatchedDigest at both sites and widen the sentinel's doc comment to cover every detection point, not just ReadAll(). The malformed-header branch keeps its unwrapped error, and the message text is otherwise unchanged. Extend the two subtests that already drive these paths with the errors.Is assertion; both fail against unmodified main. Fixes #1470 Signed-off-by: fuleinist <1163738+fuleinist@users.noreply.github.com>
1 parent c3de6f8 commit f55806a

3 files changed

Lines changed: 12 additions & 4 deletions

File tree

‎content/reader.go‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ var (
4040
// the descriptor has an invalid size.
4141
ErrInvalidDescriptorSize = errors.New("invalid descriptor size")
4242

43-
// ErrMismatchedDigest is returned by ReadAll() when
44-
// the descriptor has an invalid digest.
43+
// ErrMismatchedDigest is returned when content does not match the digest
44+
// recorded in its descriptor, wherever that mismatch is detected: by
45+
// ReadAll() for a descriptor with an invalid digest, and by a registry
46+
// client whose response digest disagrees with the requested digest.
4547
ErrMismatchedDigest = errors.New("mismatched digest")
4648

4749
// ErrTrailingData is returned by ReadAll() when

‎registry/remote/repository.go‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,10 +2209,11 @@ func (s *manifestStore) generateDescriptor(resp *http.Response, ref properties.R
22092209

22102210
if len(refDigest) > 0 && refDigest != contentDigest {
22112211
return ocispec.Descriptor{}, fmt.Errorf(
2212-
"%s %q: invalid response; digest mismatch in %s: received %q when expecting %q",
2212+
"%s %q: invalid response; digest mismatch in %s: received %q when expecting %q; %w",
22132213
resp.Request.Method, resp.Request.URL,
22142214
headerDockerContentDigest, contentDigest,
22152215
refDigest,
2216+
content.ErrMismatchedDigest,
22162217
)
22172218
}
22182219

@@ -2260,10 +2261,11 @@ func verifyContentDigest(resp *http.Response, expected digest.Digest) error {
22602261

22612262
if contentDigest != expected {
22622263
return fmt.Errorf(
2263-
"%s %q: invalid response; digest mismatch in %s: received %q when expecting %q",
2264+
"%s %q: invalid response; digest mismatch in %s: received %q when expecting %q; %w",
22642265
resp.Request.Method, resp.Request.URL,
22652266
headerDockerContentDigest, contentDigest,
22662267
expected,
2268+
content.ErrMismatchedDigest,
22672269
)
22682270
}
22692271

‎registry/remote/repository_test.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3373,6 +3373,8 @@ func Test_BlobStore_Fetch_BadResponse(t *testing.T) {
33733373

33743374
if _, err = store.Fetch(ctx, blobDesc); err == nil {
33753375
t.Error("Blobs.Fetch() error = nil, want error")
3376+
} else if !errors.Is(err, content.ErrMismatchedDigest) {
3377+
t.Errorf("Blobs.Fetch() error = %v, want %v", err, content.ErrMismatchedDigest)
33763378
}
33773379
})
33783380

@@ -4326,6 +4328,8 @@ func Test_ManifestStore_Fetch(t *testing.T) {
43264328
_, err = store.Fetch(ctx, manifestDesc)
43274329
if err == nil {
43284330
t.Error("Manifests.Fetch() error = nil, wantErr = true")
4331+
} else if !errors.Is(err, content.ErrMismatchedDigest) {
4332+
t.Errorf("Manifests.Fetch() error = %v, want %v", err, content.ErrMismatchedDigest)
43294333
}
43304334
})
43314335
}

0 commit comments

Comments
 (0)