File CVE-2024-3727.patch of Package podman.34731

From 4079fb13d7bd002c5f87ed435cd4233ffe537136 Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Tue, 2 Jul 2024 13:22:15 +0530
Subject: [PATCH 1/4] Validate the tags returned by a registry
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
 .../github.com/containers/image/v5/docker/docker_image.go  | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/vendor/github.com/containers/image/v5/docker/docker_image.go b/vendor/github.com/containers/image/v5/docker/docker_image.go
index 479effa593d9..2f3f4fad9915 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image.go
@@ -80,7 +80,12 @@ func GetRepositoryTags(ctx context.Context, sys *types.SystemContext, ref types.
 		if err = json.NewDecoder(res.Body).Decode(&tagsHolder); err != nil {
 			return nil, err
 		}
-		tags = append(tags, tagsHolder.Tags...)
+		for _, tag := range tagsHolder.Tags {
+			if _, err := reference.WithTag(dr.ref, tag); err != nil { // Ensure the tag does not contain unexpected values
+				return nil, fmt.Errorf("registry returned invalid tag %q: %w", tag, err)
+			}
+			tags = append(tags, tag)
+		}
 
 		link := res.Header.Get("Link")
 		if link == "" {
-- 
2.45.2


From 70109ddc29a3e7f7551e2086b3a07f5e41aaf9ff Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Tue, 2 Jul 2024 13:24:52 +0530
Subject: [PATCH 2/4] Call .Validate() before digest.Digest.String() if
 necessary
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

to prevent unexpected behavior on invalid values.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
 .../image/v5/docker/docker_client.go          |  3 +
 .../image/v5/docker/docker_image_dest.go      | 18 ++++--
 .../image/v5/docker/docker_image_src.go       | 16 +++++-
 .../image/v5/docker/internal/tarfile/dest.go  | 12 +++-
 .../v5/docker/internal/tarfile/writer.go      | 34 +++++++++---
 .../containers/image/v5/docker/lookaside.go   |  9 ++-
 .../image/v5/openshift/openshift.go           |  3 +
 .../image/v5/storage/storage_image.go         | 55 ++++++++++++++-----
 .../image/v5/storage/storage_reference.go     | 16 +++++-
 9 files changed, 132 insertions(+), 34 deletions(-)

diff --git a/vendor/github.com/containers/image/v5/docker/docker_client.go b/vendor/github.com/containers/image/v5/docker/docker_client.go
index e4308def1f33..e3bc5ce92a58 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_client.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_client.go
@@ -786,6 +786,9 @@ func (c *dockerClient) detectProperties(ctx context.Context) error {
 // getExtensionsSignatures returns signatures from the X-Registry-Supports-Signatures API extension,
 // using the original data structures.
 func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerReference, manifestDigest digest.Digest) (*extensionSignatureList, error) {
+	if err := manifestDigest.Validate(); err != nil { // Make sure manifestDigest.String() does not contain any unexpected characters
+		return nil, err
+	}
 	path := fmt.Sprintf(extensionsSignaturePath, reference.Path(ref.ref), manifestDigest)
 	res, err := c.makeRequest(ctx, "GET", path, nil, nil, v2Auth, nil)
 	if err != nil {
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
index 576dec4955b5..bf1da220449b 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
@@ -212,6 +212,9 @@ func (d *dockerImageDestination) PutBlob(ctx context.Context, stream io.Reader,
 // If the destination does not contain the blob, or it is unknown, blobExists ordinarily returns (false, -1, nil);
 // it returns a non-nil error only on an unexpected failure.
 func (d *dockerImageDestination) blobExists(ctx context.Context, repo reference.Named, digest digest.Digest, extraScope *authScope) (bool, int64, error) {
+	if err := digest.Validate(); err != nil { // Make sure digest.String() does not contain any unexpected characters
+		return false, -1, err
+	}
 	checkPath := fmt.Sprintf(blobsPath, reference.Path(repo), digest.String())
 	logrus.Debugf("Checking %s", checkPath)
 	res, err := d.c.makeRequest(ctx, "HEAD", checkPath, nil, nil, v2Auth, extraScope)
@@ -373,6 +376,7 @@ func (d *dockerImageDestination) PutManifest(ctx context.Context, m []byte, inst
 		// particular instance.
 		refTail = instanceDigest.String()
 		// Double-check that the manifest we've been given matches the digest we've been given.
+		// This also validates the format of instanceDigest.
 		matches, err := manifest.MatchesDigest(m, *instanceDigest)
 		if err != nil {
 			return errors.Wrapf(err, "error digesting manifest in PutManifest")
@@ -501,12 +505,14 @@ func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte, m
 
 	// NOTE: Keep this in sync with docs/signature-protocols.md!
 	for i, signature := range signatures {
-		url := signatureStorageURL(d.c.signatureBase, manifestDigest, i)
+		url, err := signatureStorageURL(d.c.signatureBase, manifestDigest, i)
+		if err != nil {
+			return err
+		}
 		if url == nil {
 			return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
 		}
-		err := d.putOneSignature(url, signature)
-		if err != nil {
+		if err := d.putOneSignature(url, signature); err != nil {
 			return err
 		}
 	}
@@ -516,7 +522,10 @@ func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte, m
 	// is enough for dockerImageSource to stop looking for other signatures, so that
 	// is sufficient.
 	for i := len(signatures); ; i++ {
-		url := signatureStorageURL(d.c.signatureBase, manifestDigest, i)
+		url, err := signatureStorageURL(d.c.signatureBase, manifestDigest, i)
+		if err != nil {
+			return err
+		}
 		if url == nil {
 			return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
 		}
@@ -628,6 +637,7 @@ sigExists:
 			return err
 		}
 
+		// manifestDigest is known to be valid because it was not rejected by getExtensionsSignatures above.
 		path := fmt.Sprintf(extensionsSignaturePath, reference.Path(d.ref.ref), manifestDigest.String())
 		res, err := d.c.makeRequest(ctx, "PUT", path, nil, bytes.NewReader(body), v2Auth, nil)
 		if err != nil {
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_src.go b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
index 4d2a9ed6c404..47e52aa10df1 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_src.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
@@ -171,6 +171,9 @@ func simplifyContentType(contentType string) string {
 // this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
 func (s *dockerImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
 	if instanceDigest != nil {
+		if err := instanceDigest.Validate(); err != nil { // Make sure instanceDigest.String() does not contain any unexpected characters
+			return nil, "", err
+		}
 		return s.fetchManifest(ctx, instanceDigest.String())
 	}
 	err := s.ensureManifestIsLoaded(ctx)
@@ -275,6 +278,9 @@ func (s *dockerImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
 		return s.getExternalBlob(ctx, info.URLs)
 	}
 
+	if err := info.Digest.Validate(); err != nil { // Make sure info.Digest.String() does not contain any unexpected characters
+		return nil, 0, err
+	}
 	path := fmt.Sprintf(blobsPath, reference.Path(s.physicalRef.ref), info.Digest.String())
 	logrus.Debugf("Downloading %s", path)
 	res, err := s.c.makeRequest(ctx, "GET", path, nil, nil, v2Auth, nil)
@@ -335,7 +341,10 @@ func (s *dockerImageSource) getSignaturesFromLookaside(ctx context.Context, inst
 	// NOTE: Keep this in sync with docs/signature-protocols.md!
 	signatures := [][]byte{}
 	for i := 0; ; i++ {
-		url := signatureStorageURL(s.c.signatureBase, manifestDigest, i)
+		url, err := signatureStorageURL(s.c.signatureBase, manifestDigest, i)
+		if err != nil {
+			return err
+		}
 		if url == nil {
 			return nil, errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
 		}
@@ -481,7 +490,10 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere
 		}
 
 		for i := 0; ; i++ {
-			url := signatureStorageURL(c.signatureBase, manifestDigest, i)
+			url, err := signatureStorageURL(c.signatureBase, manifestDigest, i)
+			if err != nil {
+				return err
+			}
 			if url == nil {
 				return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
 			}
diff --git a/vendor/github.com/containers/image/v5/docker/internal/tarfile/dest.go b/vendor/github.com/containers/image/v5/docker/internal/tarfile/dest.go
index 8c38094cfab2..c151d4970687 100644
--- a/vendor/github.com/containers/image/v5/docker/internal/tarfile/dest.go
+++ b/vendor/github.com/containers/image/v5/docker/internal/tarfile/dest.go
@@ -143,11 +143,19 @@ func (d *Destination) PutBlob(ctx context.Context, stream io.Reader, inputInfo t
 			return types.BlobInfo{}, errors.Wrap(err, "Error reading Config file stream")
 		}
 		d.config = buf
-		if err := d.archive.sendFileLocked(d.archive.configPath(inputInfo.Digest), inputInfo.Size, bytes.NewReader(buf)); err != nil {
+		configPath, err := d.archive.configPath(inputInfo.Digest)
+		if err != nil {
+			return types.BlobInfo{}, err
+		}
+		if err := d.archive.sendFileLocked(configPath, inputInfo.Size, bytes.NewReader(buf)); err != nil {
 			return types.BlobInfo{}, errors.Wrap(err, "Error writing Config file")
 		}
 	} else {
-		if err := d.archive.sendFileLocked(d.archive.physicalLayerPath(inputInfo.Digest), inputInfo.Size, stream); err != nil {
+		layerPath, err := d.archive.physicalLayerPath(inputInfo.Digest)
+		if err != nil {
+			return types.BlobInfo{}, err
+		}
+		if err := d.archive.sendFileLocked(layerPath, inputInfo.Size, stream); err != nil {
 			return types.BlobInfo{}, err
 		}
 	}
diff --git a/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go b/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go
index fd2c461d0761..ef73fe04b44a 100644
--- a/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go
+++ b/vendor/github.com/containers/image/v5/docker/internal/tarfile/writer.go
@@ -92,7 +92,10 @@ func (w *Writer) ensureSingleLegacyLayerLocked(layerID string, layerDigest diges
 	if _, ok := w.legacyLayers[layerID]; !ok {
 		// Create a symlink for the legacy format, where there is one subdirectory per layer ("image").
 		// See also the comment in physicalLayerPath.
-		physicalLayerPath := w.physicalLayerPath(layerDigest)
+		physicalLayerPath, err := w.physicalLayerPath(layerDigest)
+		if err != nil {
+			return err
+		}
 		if err := w.sendSymlinkLocked(filepath.Join(layerID, legacyLayerFileName), filepath.Join("..", physicalLayerPath)); err != nil {
 			return errors.Wrap(err, "Error creating layer symbolic link")
 		}
@@ -136,6 +139,9 @@ func (w *Writer) writeLegacyMetadataLocked(layerDescriptors []manifest.Schema2De
 		}
 
 		// This chainID value matches the computation in docker/docker/layer.CreateChainID …
+		if err := l.Digest.Validate(); err != nil { // This should never fail on this code path, still: make sure the chainID computation is unambiguous.
+			return err
+		}
 		if chainID == "" {
 			chainID = l.Digest
 		} else {
@@ -206,12 +212,20 @@ func checkManifestItemsMatch(a, b *ManifestItem) error {
 func (w *Writer) ensureManifestItemLocked(layerDescriptors []manifest.Schema2Descriptor, configDigest digest.Digest, repoTags []reference.NamedTagged) error {
 	layerPaths := []string{}
 	for _, l := range layerDescriptors {
-		layerPaths = append(layerPaths, w.physicalLayerPath(l.Digest))
+		p, err := w.physicalLayerPath(l.Digest)
+		if err != nil {
+			return err
+		}
+		layerPaths = append(layerPaths, p)
 	}
 
 	var item *ManifestItem
+	configPath, err := w.configPath(configDigest)
+	if err != nil {
+		return err
+	}
 	newItem := ManifestItem{
-		Config:       w.configPath(configDigest),
+		Config:       configPath,
 		RepoTags:     []string{},
 		Layers:       layerPaths,
 		Parent:       "", // We don’t have this information
@@ -296,21 +310,27 @@ func (w *Writer) Close() error {
 // configPath returns a path we choose for storing a config with the specified digest.
 // NOTE: This is an internal implementation detail, not a format property, and can change
 // any time.
-func (w *Writer) configPath(configDigest digest.Digest) string {
-	return configDigest.Hex() + ".json"
+func (w *Writer) configPath(configDigest digest.Digest) (string, error) {
+	if err := configDigest.Validate(); err != nil { // digest.Digest.Hex() panics on failure, and could possibly result in unexpected paths, so validate explicitly.
+		return "", err
+	}
+	return configDigest.Hex() + ".json", nil
 }
 
 // physicalLayerPath returns a path we choose for storing a layer with the specified digest
 // (the actual path, i.e. a regular file, not a symlink that may be used in the legacy format).
 // NOTE: This is an internal implementation detail, not a format property, and can change
 // any time.
-func (w *Writer) physicalLayerPath(layerDigest digest.Digest) string {
+func (w *Writer) physicalLayerPath(layerDigest digest.Digest) (string, error) {
+	if err := layerDigest.Validate(); err != nil { // digest.Digest.Hex() panics on failure, and could possibly result in unexpected paths, so validate explicitly.
+		return "", err
+	}
 	// Note that this can't be e.g. filepath.Join(l.Digest.Hex(), legacyLayerFileName); due to the way
 	// writeLegacyMetadata constructs layer IDs differently from inputinfo.Digest values (as described
 	// inside it), most of the layers would end up in subdirectories alone without any metadata; (docker load)
 	// tries to load every subdirectory as an image and fails if the config is missing.  So, keep the layers
 	// in the root of the tarball.
-	return layerDigest.Hex() + ".tar"
+	return layerDigest.Hex() + ".tar", nil
 }
 
 type tarFI struct {
diff --git a/vendor/github.com/containers/image/v5/docker/lookaside.go b/vendor/github.com/containers/image/v5/docker/lookaside.go
index 6931fd07baed..07a8f31dd9e7 100644
--- a/vendor/github.com/containers/image/v5/docker/lookaside.go
+++ b/vendor/github.com/containers/image/v5/docker/lookaside.go
@@ -199,11 +199,14 @@ func (ns registryNamespace) signatureTopLevel(write bool) string {
 // signatureStorageURL returns an URL usable for acessing signature index in base with known manifestDigest, or nil if not applicable.
 // Returns nil iff base == nil.
 // NOTE: Keep this in sync with docs/signature-protocols.md!
-func signatureStorageURL(base signatureStorageBase, manifestDigest digest.Digest, index int) *url.URL {
+func signatureStorageURL(base signatureStorageBase, manifestDigest digest.Digest, index int) (*url.URL, error) {
+	if err := manifestDigest.Validate(); err != nil { // digest.Digest.Hex() panics on failure, and could possibly result in a path with ../, so validate explicitly.
+		return nil, err
+	}
 	if base == nil {
-		return nil
+		return nil, nil
 	}
 	url := *base
 	url.Path = fmt.Sprintf("%s@%s=%s/signature-%d", url.Path, manifestDigest.Algorithm(), manifestDigest.Hex(), index+1)
-	return &url
+	return &url, nil
 }
diff --git a/vendor/github.com/containers/image/v5/openshift/openshift.go b/vendor/github.com/containers/image/v5/openshift/openshift.go
index 28bfc456d565..a3ae4467890d 100644
--- a/vendor/github.com/containers/image/v5/openshift/openshift.go
+++ b/vendor/github.com/containers/image/v5/openshift/openshift.go
@@ -238,6 +238,9 @@ func (s *openshiftImageSource) GetSignatures(ctx context.Context, instanceDigest
 		}
 		imageStreamImageName = s.imageStreamImageName
 	} else {
+		if err := instanceDigest.Validate(); err != nil { // Make sure instanceDigest.String() does not contain any unexpected characters
+			return nil, err
+		}
 		imageStreamImageName = instanceDigest.String()
 	}
 	image, err := s.client.getImage(ctx, imageStreamImageName)
diff --git a/vendor/github.com/containers/image/v5/storage/storage_image.go b/vendor/github.com/containers/image/v5/storage/storage_image.go
index df4b67c7a747..18bdd78a99bd 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_image.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_image.go
@@ -1,3 +1,4 @@
+//go:build !containers_image_storage_stub
 // +build !containers_image_storage_stub
 
 package storage
@@ -75,14 +76,20 @@ type storageImageCloser struct {
 // manifestBigDataKey returns a key suitable for recording a manifest with the specified digest using storage.Store.ImageBigData and related functions.
 // If a specific manifest digest is explicitly requested by the user, the key returned by this function should be used preferably;
 // for compatibility, if a manifest is not available under this key, check also storage.ImageDigestBigDataKey
-func manifestBigDataKey(digest digest.Digest) string {
-	return storage.ImageDigestManifestBigDataNamePrefix + "-" + digest.String()
+func manifestBigDataKey(digest digest.Digest) (string, error) {
+	if err := digest.Validate(); err != nil { // Make sure info.Digest.String() uses the expected format and does not collide with other BigData keys.
+		return "", err
+	}
+	return storage.ImageDigestManifestBigDataNamePrefix + "-" + digest.String(), nil
 }
 
 // signatureBigDataKey returns a key suitable for recording the signatures associated with the manifest with the specified digest using storage.Store.ImageBigData and related functions.
 // If a specific manifest digest is explicitly requested by the user, the key returned by this function should be used preferably;
-func signatureBigDataKey(digest digest.Digest) string {
-	return "signature-" + digest.Encoded()
+func signatureBigDataKey(digest digest.Digest) (string, error) {
+	if err := digest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, so validate explicitly.
+		return "", err
+	}
+	return "signature-" + digest.Encoded(), nil
 }
 
 // newImageSource sets up an image for reading.
@@ -191,7 +198,10 @@ func (s *storageImageSource) getBlobAndLayerID(info types.BlobInfo) (rc io.ReadC
 // GetManifest() reads the image's manifest.
 func (s *storageImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) (manifestBlob []byte, MIMEType string, err error) {
 	if instanceDigest != nil {
-		key := manifestBigDataKey(*instanceDigest)
+		key, err := manifestBigDataKey(*instanceDigest)
+		if err != nil {
+			return nil, "", err
+		}
 		blob, err := s.imageRef.transport.store.ImageBigData(s.image.ID, key)
 		if err != nil {
 			return nil, "", errors.Wrapf(err, "error reading manifest for image instance %q", *instanceDigest)
@@ -203,7 +213,10 @@ func (s *storageImageSource) GetManifest(ctx context.Context, instanceDigest *di
 		// Prefer the manifest corresponding to the user-specified digest, if available.
 		if s.imageRef.named != nil {
 			if digested, ok := s.imageRef.named.(reference.Digested); ok {
-				key := manifestBigDataKey(digested.Digest())
+				key, err := manifestBigDataKey(digested.Digest())
+				if err != nil {
+					return nil, "", err
+				}
 				blob, err := s.imageRef.transport.store.ImageBigData(s.image.ID, key)
 				if err != nil && !os.IsNotExist(err) { // os.IsNotExist is true if the image exists but there is no data corresponding to key
 					return nil, "", err
@@ -317,7 +330,14 @@ func (s *storageImageSource) GetSignatures(ctx context.Context, instanceDigest *
 	instance := "default instance"
 	if instanceDigest != nil {
 		signatureSizes = s.SignaturesSizes[*instanceDigest]
-		key = signatureBigDataKey(*instanceDigest)
+		k, err := signatureBigDataKey(*instanceDigest)
+		if err != nil {
+			return nil, err
+		}
+		key = k
+		if err := instanceDigest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, so validate explicitly.
+			return nil, err
+		}
 		instance = instanceDigest.Encoded()
 	}
 	if len(signatureSizes) > 0 {
@@ -467,15 +487,15 @@ func (s *storageImageDestination) PutBlob(ctx context.Context, stream io.Reader,
 // If the transport can not reuse the requested blob, TryReusingBlob returns (false, {}, nil); it returns a non-nil error only on an unexpected failure.
 // May use and/or update cache.
 func (s *storageImageDestination) TryReusingBlob(ctx context.Context, blobinfo types.BlobInfo, cache types.BlobInfoCache, canSubstitute bool) (bool, types.BlobInfo, error) {
-	// lock the entire method as it executes fairly quickly
-	s.putBlobMutex.Lock()
-	defer s.putBlobMutex.Unlock()
 	if blobinfo.Digest == "" {
 		return false, types.BlobInfo{}, errors.Errorf(`Can not check for a blob with unknown digest`)
 	}
 	if err := blobinfo.Digest.Validate(); err != nil {
 		return false, types.BlobInfo{}, errors.Wrapf(err, `Can not check for a blob with invalid digest`)
 	}
+	// lock the entire method as it executes fairly quickly
+	s.putBlobMutex.Lock()
+	defer s.putBlobMutex.Unlock()
 
 	// Check if we've already cached it in a file.
 	if size, ok := s.fileSizes[blobinfo.Digest]; ok {
@@ -826,7 +846,10 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
 		if err != nil {
 			return errors.Wrapf(err, "error digesting top-level manifest")
 		}
-		key := manifestBigDataKey(manifestDigest)
+		key, err := manifestBigDataKey(manifestDigest)
+		if err != nil {
+			return err
+		}
 		if err := s.imageRef.transport.store.SetImageBigData(img.ID, key, toplevelManifest, manifest.Digest); err != nil {
 			if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil {
 				logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2)
@@ -842,7 +865,10 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
 	if err != nil {
 		return errors.Wrapf(err, "error computing manifest digest")
 	}
-	key := manifestBigDataKey(manifestDigest)
+	key, err := manifestBigDataKey(manifestDigest)
+	if err != nil {
+		return err
+	}
 	if err := s.imageRef.transport.store.SetImageBigData(img.ID, key, s.manifest, manifest.Digest); err != nil {
 		if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil {
 			logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2)
@@ -869,7 +895,10 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
 		}
 	}
 	for instanceDigest, signatures := range s.signatureses {
-		key := signatureBigDataKey(instanceDigest)
+		key, err := signatureBigDataKey(instanceDigest)
+		if err != nil {
+			return err
+		}
 		if err := s.imageRef.transport.store.SetImageBigData(img.ID, key, signatures, manifest.Digest); err != nil {
 			if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil {
 				logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2)
diff --git a/vendor/github.com/containers/image/v5/storage/storage_reference.go b/vendor/github.com/containers/image/v5/storage/storage_reference.go
index 394557f39a39..2cd4cfcde3ce 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_reference.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_reference.go
@@ -1,3 +1,4 @@
+//go:build !containers_image_storage_stub
 // +build !containers_image_storage_stub
 
 package storage
@@ -74,7 +75,10 @@ func imageMatchesRepo(image *storage.Image, ref reference.Named) bool {
 func imageMatchesSystemContext(store storage.Store, img *storage.Image, manifestDigest digest.Digest, sys *types.SystemContext) bool {
 	// First, check if the image record has a manifest that matches the
 	// specified digest.
-	key := manifestBigDataKey(manifestDigest)
+	key, err := manifestBigDataKey(manifestDigest)
+	if err != nil {
+		return false // This should never happen, manifestDigest comes from a reference.Digested, and that validates the format.
+	}
 	manifestBytes, err := store.ImageBigData(img.ID, key)
 	if err != nil {
 		return false
@@ -92,7 +96,10 @@ func imageMatchesSystemContext(store storage.Store, img *storage.Image, manifest
 		if err != nil {
 			return false
 		}
-		key = manifestBigDataKey(manifestDigest)
+		key, err := manifestBigDataKey(manifestDigest)
+		if err != nil {
+			return false // This should never happen, manifestDigest comes from a reference.Digested, and that validates the format.
+		}
 		manifestBytes, err = store.ImageBigData(img.ID, key)
 		if err != nil {
 			return false
@@ -130,7 +137,10 @@ func imageMatchesSystemContext(store storage.Store, img *storage.Image, manifest
 	}
 	// Double-check that we can read the runnable image's manifest from the
 	// image record.
-	key = manifestBigDataKey(instanceDigest)
+	key, err := manifestBigDataKey(instanceDigest)
+	if err != nil {
+		return false // This should never happen, manifestDigest comes from a reference.Digested, and that validates the format.
+	}
 	_, err = store.ImageBigData(img.ID, key)
 	return err == nil
 }
-- 
2.45.2


From ae5b155320dbef382d699d3d43b1eb962239a228 Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Tue, 2 Jul 2024 13:26:51 +0530
Subject: [PATCH 3/4] Call .Validate() before digest.Hex() / digest.Encoded()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

to prevent panics if the value does not contain a :, or other unexpected
values (e.g. a path traversal).

Don't bother on paths where we computed the digest ourselves, or it is already trusted
for other reasons.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
 .../containers/image/v5/copy/copy.go          | 23 +++++++++++++----
 .../image/v5/directory/directory_dest.go      | 22 +++++++++++++---
 .../image/v5/directory/directory_src.go       | 18 ++++++++++---
 .../image/v5/directory/directory_transport.go | 25 +++++++++++++------
 .../containers/image/v5/ostree/ostree_dest.go | 10 ++++++++
 .../containers/image/v5/ostree/ostree_src.go  |  5 +++-
 6 files changed, 82 insertions(+), 21 deletions(-)

diff --git a/vendor/github.com/containers/image/v5/copy/copy.go b/vendor/github.com/containers/image/v5/copy/copy.go
index 873bdc67f4ba..5a5b98c52f09 100644
--- a/vendor/github.com/containers/image/v5/copy/copy.go
+++ b/vendor/github.com/containers/image/v5/copy/copy.go
@@ -963,10 +963,14 @@ func (c *copier) newProgressPool(ctx context.Context) (*mpb.Progress, func()) {
 
 // createProgressBar creates a mpb.Bar in pool.  Note that if the copier's reportWriter
 // is ioutil.Discard, the progress bar's output will be discarded
-func (c *copier) createProgressBar(pool *mpb.Progress, info types.BlobInfo, kind string, onComplete string) *mpb.Bar {
+func (c *copier) createProgressBar(pool *mpb.Progress, info types.BlobInfo, kind string, onComplete string) (*mpb.Bar, error) {
 	// shortDigestLen is the length of the digest used for blobs.
 	const shortDigestLen = 12
 
+	if err := info.Digest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, so validate explicitly.
+		return nil, err
+	}
+
 	prefix := fmt.Sprintf("Copying %s %s", kind, info.Digest.Encoded())
 	// Truncate the prefix (chopping of some part of the digest) to make all progress bars aligned in a column.
 	maxPrefixLen := len("Copying blob ") + shortDigestLen
@@ -1003,7 +1007,7 @@ func (c *copier) createProgressBar(pool *mpb.Progress, info types.BlobInfo, kind
 	if c.progressOutput == ioutil.Discard {
 		c.Printf("Copying %s %s\n", kind, info.Digest)
 	}
-	return bar
+	return bar, nil
 }
 
 // copyConfig copies config.json, if any, from src to dest.
@@ -1018,7 +1022,10 @@ func (c *copier) copyConfig(ctx context.Context, src types.Image) error {
 		destInfo, err := func() (types.BlobInfo, error) { // A scope for defer
 			progressPool, progressCleanup := c.newProgressPool(ctx)
 			defer progressCleanup()
-			bar := c.createProgressBar(progressPool, srcInfo, "config", "done")
+			bar, err := c.createProgressBar(progressPool, srcInfo, "config", "done")
+			if err != nil {
+				return types.BlobInfo{}, err
+			}
 			destInfo, err := c.copyBlobFromStream(ctx, bytes.NewReader(configBlob), srcInfo, nil, false, true, false, bar)
 			if err != nil {
 				return types.BlobInfo{}, err
@@ -1058,7 +1065,10 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to
 		}
 		if reused {
 			logrus.Debugf("Skipping blob %s (already present):", srcInfo.Digest)
-			bar := ic.c.createProgressBar(pool, srcInfo, "blob", "skipped: already exists")
+			bar, err := ic.c.createProgressBar(pool, srcInfo, "blob", "skipped: already exists")
+			if err != nil {
+				return types.BlobInfo{}, "", err
+			}
 			bar.SetTotal(0, true)
 
 			// Throw an event that the layer has been skipped
@@ -1079,7 +1089,10 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to
 	}
 	defer srcStream.Close()
 
-	bar := ic.c.createProgressBar(pool, srcInfo, "blob", "done")
+	bar, err := ic.c.createProgressBar(pool, srcInfo, "blob", "done")
+	if err != nil {
+		return types.BlobInfo{}, "", err
+	}
 
 	blobInfo, diffIDChan, err := ic.copyLayerFromStream(ctx, srcStream, types.BlobInfo{Digest: srcInfo.Digest, Size: srcBlobSize, MediaType: srcInfo.MediaType, Annotations: srcInfo.Annotations}, diffIDIsNeeded, toEncrypt, bar)
 	if err != nil {
diff --git a/vendor/github.com/containers/image/v5/directory/directory_dest.go b/vendor/github.com/containers/image/v5/directory/directory_dest.go
index d70b6c07fbca..46ca7b12528b 100644
--- a/vendor/github.com/containers/image/v5/directory/directory_dest.go
+++ b/vendor/github.com/containers/image/v5/directory/directory_dest.go
@@ -179,7 +179,10 @@ func (d *dirImageDestination) PutBlob(ctx context.Context, stream io.Reader, inp
 		}
 	}
 
-	blobPath := d.ref.layerPath(computedDigest)
+	blobPath, err := d.ref.layerPath(computedDigest)
+	if err != nil {
+		return types.BlobInfo{}, err
+	}
 	// need to explicitly close the file, since a rename won't otherwise not work on Windows
 	blobFile.Close()
 	explicitClosed = true
@@ -201,7 +204,10 @@ func (d *dirImageDestination) TryReusingBlob(ctx context.Context, info types.Blo
 	if info.Digest == "" {
 		return false, types.BlobInfo{}, errors.Errorf(`"Can not check for a blob with unknown digest`)
 	}
-	blobPath := d.ref.layerPath(info.Digest)
+	blobPath, err := d.ref.layerPath(info.Digest)
+	if err != nil {
+		return false, types.BlobInfo{}, err
+	}
 	finfo, err := os.Stat(blobPath)
 	if err != nil && os.IsNotExist(err) {
 		return false, types.BlobInfo{}, nil
@@ -222,7 +228,11 @@ func (d *dirImageDestination) TryReusingBlob(ctx context.Context, info types.Blo
 // If the destination is in principle available, refuses this manifest type (e.g. it does not recognize the schema),
 // but may accept a different manifest type, the returned error must be an ManifestTypeRejectedError.
 func (d *dirImageDestination) PutManifest(ctx context.Context, manifest []byte, instanceDigest *digest.Digest) error {
-	return ioutil.WriteFile(d.ref.manifestPath(instanceDigest), manifest, 0644)
+	path, err := d.ref.manifestPath(instanceDigest)
+	if err != nil {
+		return err
+	}
+	return ioutil.WriteFile(path, manifest, 0644)
 }
 
 // PutSignatures writes a set of signatures to the destination.
@@ -230,7 +240,11 @@ func (d *dirImageDestination) PutManifest(ctx context.Context, manifest []byte,
 // (when the primary manifest is a manifest list); this should always be nil if the primary manifest is not a manifest list.
 func (d *dirImageDestination) PutSignatures(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error {
 	for i, sig := range signatures {
-		if err := ioutil.WriteFile(d.ref.signaturePath(i, instanceDigest), sig, 0644); err != nil {
+		path, err := d.ref.signaturePath(i, instanceDigest)
+		if err != nil {
+			return err
+		}
+		if err := ioutil.WriteFile(path, sig, 0644); err != nil {
 			return err
 		}
 	}
diff --git a/vendor/github.com/containers/image/v5/directory/directory_src.go b/vendor/github.com/containers/image/v5/directory/directory_src.go
index ad9129d4012b..420cee2fda54 100644
--- a/vendor/github.com/containers/image/v5/directory/directory_src.go
+++ b/vendor/github.com/containers/image/v5/directory/directory_src.go
@@ -37,7 +37,11 @@ func (s *dirImageSource) Close() error {
 // If instanceDigest is not nil, it contains a digest of the specific manifest instance to retrieve (when the primary manifest is a manifest list);
 // this never happens if the primary manifest is not a manifest list (e.g. if the source never returns manifest lists).
 func (s *dirImageSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
-	m, err := ioutil.ReadFile(s.ref.manifestPath(instanceDigest))
+	path, err := s.ref.manifestPath(instanceDigest)
+	if err != nil {
+		return nil, "", err
+	}
+	m, err := ioutil.ReadFile(path)
 	if err != nil {
 		return nil, "", err
 	}
@@ -53,7 +57,11 @@ func (s *dirImageSource) HasThreadSafeGetBlob() bool {
 // The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided.
 // May update BlobInfoCache, preferably after it knows for certain that a blob truly exists at a specific location.
 func (s *dirImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {
-	r, err := os.Open(s.ref.layerPath(info.Digest))
+	path, err := s.ref.layerPath(info.Digest)
+	if err != nil {
+		return nil, -1, err
+	}
+	r, err := os.Open(path)
 	if err != nil {
 		return nil, -1, err
 	}
@@ -71,7 +79,11 @@ func (s *dirImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache
 func (s *dirImageSource) GetSignatures(ctx context.Context, instanceDigest *digest.Digest) ([][]byte, error) {
 	signatures := [][]byte{}
 	for i := 0; ; i++ {
-		signature, err := ioutil.ReadFile(s.ref.signaturePath(i, instanceDigest))
+		path, err := s.ref.signaturePath(i, instanceDigest)
+		if err != nil {
+			return nil, err
+		}
+		signature, err := ioutil.ReadFile(path)
 		if err != nil {
 			if os.IsNotExist(err) {
 				break
diff --git a/vendor/github.com/containers/image/v5/directory/directory_transport.go b/vendor/github.com/containers/image/v5/directory/directory_transport.go
index adfec6ef3737..d1300b867c09 100644
--- a/vendor/github.com/containers/image/v5/directory/directory_transport.go
+++ b/vendor/github.com/containers/image/v5/directory/directory_transport.go
@@ -166,25 +166,34 @@ func (ref dirReference) DeleteImage(ctx context.Context, sys *types.SystemContex
 }
 
 // manifestPath returns a path for the manifest within a directory using our conventions.
-func (ref dirReference) manifestPath(instanceDigest *digest.Digest) string {
+func (ref dirReference) manifestPath(instanceDigest *digest.Digest) (string, error) {
 	if instanceDigest != nil {
-		return filepath.Join(ref.path, instanceDigest.Encoded()+".manifest.json")
+		if err := instanceDigest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, and could possibly result in a path with ../, so validate explicitly.
+			return "", err
+		}
+		return filepath.Join(ref.path, instanceDigest.Encoded()+".manifest.json"), nil
 	}
-	return filepath.Join(ref.path, "manifest.json")
+	return filepath.Join(ref.path, "manifest.json"), nil
 }
 
 // layerPath returns a path for a layer tarball within a directory using our conventions.
-func (ref dirReference) layerPath(digest digest.Digest) string {
+func (ref dirReference) layerPath(digest digest.Digest) (string, error) {
+	if err := digest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, and could possibly result in a path with ../, so validate explicitly.
+		return "", err
+	}
 	// FIXME: Should we keep the digest identification?
-	return filepath.Join(ref.path, digest.Encoded())
+	return filepath.Join(ref.path, digest.Encoded()), nil
 }
 
 // signaturePath returns a path for a signature within a directory using our conventions.
-func (ref dirReference) signaturePath(index int, instanceDigest *digest.Digest) string {
+func (ref dirReference) signaturePath(index int, instanceDigest *digest.Digest) (string, error) {
 	if instanceDigest != nil {
-		return filepath.Join(ref.path, fmt.Sprintf(instanceDigest.Encoded()+".signature-%d", index+1))
+		if err := instanceDigest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, and could possibly result in a path with ../, so validate explicitly.
+			return "", err
+		}
+		return filepath.Join(ref.path, fmt.Sprintf(instanceDigest.Encoded()+".signature-%d", index+1)), nil
 	}
-	return filepath.Join(ref.path, fmt.Sprintf("signature-%d", index+1))
+	return filepath.Join(ref.path, fmt.Sprintf("signature-%d", index+1)), nil
 }
 
 // versionPath returns a path for the version file within a directory using our conventions.
diff --git a/vendor/github.com/containers/image/v5/ostree/ostree_dest.go b/vendor/github.com/containers/image/v5/ostree/ostree_dest.go
index 11509705592a..aa708c581278 100644
--- a/vendor/github.com/containers/image/v5/ostree/ostree_dest.go
+++ b/vendor/github.com/containers/image/v5/ostree/ostree_dest.go
@@ -1,3 +1,4 @@
+//go:build containers_image_ostree
 // +build containers_image_ostree
 
 package ostree
@@ -350,6 +351,9 @@ func (d *ostreeImageDestination) TryReusingBlob(ctx context.Context, info types.
 		}
 		d.repo = repo
 	}
+	if err := info.Digest.Validate(); err != nil { // digest.Digest.Hex() panics on failure, so validate explicitly.
+		return false, types.BlobInfo{}, err
+	}
 	branch := fmt.Sprintf("ociimage/%s", info.Digest.Hex())
 
 	found, data, err := readMetadata(d.repo, branch, "docker.uncompressed_digest")
@@ -470,12 +474,18 @@ func (d *ostreeImageDestination) Commit(context.Context, types.UnparsedImage) er
 		return nil
 	}
 	for _, layer := range d.schema.LayersDescriptors {
+		if err := layer.Digest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, so validate explicitly.
+			return err
+		}
 		hash := layer.Digest.Hex()
 		if err = checkLayer(hash); err != nil {
 			return err
 		}
 	}
 	for _, layer := range d.schema.FSLayers {
+		if err := layer.BlobSum.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, so validate explicitly.
+			return err
+		}
 		hash := layer.BlobSum.Hex()
 		if err = checkLayer(hash); err != nil {
 			return err
diff --git a/vendor/github.com/containers/image/v5/ostree/ostree_src.go b/vendor/github.com/containers/image/v5/ostree/ostree_src.go
index 4948ec664161..f60cbcf7c149 100644
--- a/vendor/github.com/containers/image/v5/ostree/ostree_src.go
+++ b/vendor/github.com/containers/image/v5/ostree/ostree_src.go
@@ -1,3 +1,4 @@
+//go:build containers_image_ostree
 // +build containers_image_ostree
 
 package ostree
@@ -272,7 +273,9 @@ func (s *ostreeImageSource) HasThreadSafeGetBlob() bool {
 // The Digest field in BlobInfo is guaranteed to be provided, Size may be -1 and MediaType may be optionally provided.
 // May update BlobInfoCache, preferably after it knows for certain that a blob truly exists at a specific location.
 func (s *ostreeImageSource) GetBlob(ctx context.Context, info types.BlobInfo, cache types.BlobInfoCache) (io.ReadCloser, int64, error) {
-
+	if err := info.Digest.Validate(); err != nil { // digest.Digest.Encoded() panics on failure, so validate explicitly.
+		return nil, -1, err
+	}
 	blob := info.Digest.Hex()
 
 	// Ensure s.compressed is initialized.  It is build by LayerInfosForCopy.
-- 
2.45.2


From d916bec0f8f7882e3148922b3bed2d7281c1ee66 Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Tue, 2 Jul 2024 13:25:47 +0530
Subject: [PATCH 4/4] rename makeFilename to blobPath
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
 .../buildah/pkg/blobcache/blobcache.go        | 46 +++++++++++++++++--
 .../image/v5/docker/docker_image_src.go       |  2 +-
 .../image/v5/storage/storage_reference.go     |  2 +-
 3 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go b/vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go
index 3f0177226322..e91e3c73b02e 100644
--- a/vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go
+++ b/vendor/github.com/containers/buildah/pkg/blobcache/blobcache.go
@@ -81,6 +81,18 @@ func makeFilename(blobSum digest.Digest, isConfig bool) string {
 	return blobSum.String()
 }
 
+// blobPath returns the path appropriate for storing a blob with digest.
+func (b *blobCacheReference) blobPath(digest digest.Digest, isConfig bool) (string, error) {
+	if err := digest.Validate(); err != nil { // Make sure digest.String() does not contain any unexpected characters
+		return "", err
+	}
+	baseName := digest.String()
+	if isConfig {
+		baseName += ".config"
+	}
+	return filepath.Join(b.directory, baseName), nil
+}
+
 // NewBlobCache creates a new blob cache that wraps an image reference.  Any blobs which are
 // written to the destination image created from the resulting reference will also be stored
 // as-is to the specified directory or a temporary directory.  The cache directory's contents
@@ -134,7 +146,10 @@ func (r *blobCacheReference) HasBlob(blobinfo types.BlobInfo) (bool, int64, erro
 	}
 
 	for _, isConfig := range []bool{false, true} {
-		filename := filepath.Join(r.directory, makeFilename(blobinfo.Digest, isConfig))
+		filename, err := r.blobPath(blobinfo.Digest, isConfig)
+		if err != nil {
+			return false, -1, err
+		}
 		fileInfo, err := os.Stat(filename)
 		if err == nil && (blobinfo.Size == -1 || blobinfo.Size == fileInfo.Size()) {
 			return true, fileInfo.Size(), nil
@@ -207,7 +222,10 @@ func (s *blobCacheSource) Close() error {
 
 func (s *blobCacheSource) GetManifest(ctx context.Context, instanceDigest *digest.Digest) ([]byte, string, error) {
 	if instanceDigest != nil {
-		filename := filepath.Join(s.reference.directory, makeFilename(*instanceDigest, false))
+		filename, err := s.reference.blobPath(*instanceDigest, false)
+		if err != nil {
+			return nil, "", err
+		}
 		manifestBytes, err := ioutil.ReadFile(filename)
 		if err == nil {
 			s.cacheHits++
@@ -287,7 +305,10 @@ func (s *blobCacheSource) LayerInfosForCopy(ctx context.Context, instanceDigest
 		for _, info := range infos {
 			var replaceDigest []byte
 			var err error
-			blobFile := filepath.Join(s.reference.directory, makeFilename(info.Digest, false))
+			blobFile, err2 := s.reference.blobPath(info.Digest, false)
+			if err != nil {
+				return nil, err2
+			}
 			alternate := ""
 			switch s.reference.compress {
 			case types.Compress:
@@ -298,7 +319,10 @@ func (s *blobCacheSource) LayerInfosForCopy(ctx context.Context, instanceDigest
 				replaceDigest, err = ioutil.ReadFile(alternate)
 			}
 			if err == nil && digest.Digest(replaceDigest).Validate() == nil {
-				alternate = filepath.Join(filepath.Dir(alternate), makeFilename(digest.Digest(replaceDigest), false))
+				alternate, err := s.reference.blobPath(digest.Digest(replaceDigest), false)
+				if err != nil {
+					return nil, err
+				}
 				fileInfo, err := os.Stat(alternate)
 				if err == nil {
 					logrus.Debugf("suggesting cached blob with digest %q and compression %v in place of blob with digest %q", string(replaceDigest), s.reference.compress, info.Digest.String())
@@ -371,6 +395,7 @@ func saveStream(wg *sync.WaitGroup, decompressReader io.ReadCloser, tempFile *os
 	defer wg.Done()
 	// Decompress from and digest the reading end of that pipe.
 	decompressed, err3 := archive.DecompressStream(decompressReader)
+
 	digester := digest.Canonical.Digester()
 	if err3 == nil {
 		// Read the decompressed data through the filter over the pipe, blocking until the
@@ -382,9 +407,13 @@ func saveStream(wg *sync.WaitGroup, decompressReader io.ReadCloser, tempFile *os
 			logrus.Debugf("error draining the pipe: %v", err)
 		}
 	}
+
 	decompressReader.Close()
 	decompressed.Close()
 	tempFile.Close()
+	if err := digester.Digest().Validate(); err != nil {
+		return
+	}
 	// Determine the name that we should give to the uncompressed copy of the blob.
 	decompressedFilename := filepath.Join(filepath.Dir(tempFile.Name()), makeFilename(digester.Digest(), isConfig))
 	if err3 == nil {
@@ -427,6 +456,10 @@ func (d *blobCacheDestination) PutBlob(ctx context.Context, stream io.Reader, in
 	compression := archive.Uncompressed
 	if inputInfo.Digest != "" {
 		filename := filepath.Join(d.reference.directory, makeFilename(inputInfo.Digest, isConfig))
+		filename, err2 := d.reference.blobPath(inputInfo.Digest, isConfig)
+		if err2 != nil {
+			return types.BlobInfo{}, err2
+		}
 		tempfile, err = ioutil.TempFile(d.reference.directory, makeFilename(inputInfo.Digest, isConfig))
 		if err == nil {
 			stream = io.TeeReader(stream, tempfile)
@@ -519,7 +552,10 @@ func (d *blobCacheDestination) PutManifest(ctx context.Context, manifestBytes []
 	if err != nil {
 		logrus.Warnf("error digesting manifest %q: %v", string(manifestBytes), err)
 	} else {
-		filename := filepath.Join(d.reference.directory, makeFilename(manifestDigest, false))
+		filename, err := d.reference.blobPath(manifestDigest, false)
+		if err != nil {
+			return err
+		}
 		if err = ioutils.AtomicWriteFile(filename, manifestBytes, 0600); err != nil {
 			logrus.Warnf("error saving manifest as %q: %v", filename, err)
 		}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_src.go b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
index 47e52aa10df1..234949673ba0 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_src.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
@@ -343,7 +343,7 @@ func (s *dockerImageSource) getSignaturesFromLookaside(ctx context.Context, inst
 	for i := 0; ; i++ {
 		url, err := signatureStorageURL(s.c.signatureBase, manifestDigest, i)
 		if err != nil {
-			return err
+			return nil, err
 		}
 		if url == nil {
 			return nil, errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
diff --git a/vendor/github.com/containers/image/v5/storage/storage_reference.go b/vendor/github.com/containers/image/v5/storage/storage_reference.go
index 2cd4cfcde3ce..c3f89962fd3f 100644
--- a/vendor/github.com/containers/image/v5/storage/storage_reference.go
+++ b/vendor/github.com/containers/image/v5/storage/storage_reference.go
@@ -137,7 +137,7 @@ func imageMatchesSystemContext(store storage.Store, img *storage.Image, manifest
 	}
 	// Double-check that we can read the runnable image's manifest from the
 	// image record.
-	key, err := manifestBigDataKey(instanceDigest)
+	key, err = manifestBigDataKey(instanceDigest)
 	if err != nil {
 		return false // This should never happen, manifestDigest comes from a reference.Digested, and that validates the format.
 	}
-- 
2.45.2

openSUSE Build Service is sponsored by