core/content: Copy: restore support for "-1" as unknown size

Restore support for -1 as an unknown-size sentinel for backward
compatibility. Normalize it to 0, the documented value for unknown
sizes in the Writer interface.

Other negative sizes remain invalid, and known-size copies retain
their existing bounds checks.

Updates 91f62bdd77

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn committed 2026-10-15 13:06:31 +02:00
1 parent 4a21f73e84
commit 2f0dd596a9
2 files changed
+39 -5

No files matched your search

+9 -3
View File
@@ -188,14 +188,20 @@ func OpenWriter(ctx context.Context, cs Ingester, opts ...WriterOpt) (Writer, er
// Copy copies data with the expected digest from the reader into the
// provided content store writer. This copy commits the writer.
//
// This is useful when the digest and size are known beforehand. When
// the size or digest is unknown, these values may be empty.
// A size of 0 indicates an unknown size, in which case the reader is
// copied until EOF. For backward compatibility, -1 is also accepted
// as an unknown size. Other negative sizes are invalid. Positive sizes
// are enforced, and an empty expected digest disables digest verification.
//
// Copy is buffered, so no need to wrap reader in buffered io.
func Copy(ctx context.Context, cw Writer, or io.Reader, size int64, expected digest.Digest, opts ...Opt) error {
if size < 0 {
if size < -1 {
return fmt.Errorf("invalid content size %d: %w", size, errdefs.ErrInvalidArgument)
}
if size == -1 {
// Writer.Commit uses 0 for an unknown size.
size = 0
}
for i := 0; ; i++ {
if i >= 1 {
log.G(ctx).WithField("digest", expected).Debugf("retrying copy due to reset")
+30 -2
View File
@@ -205,10 +205,34 @@ func TestCopy(t *testing.T) {
expectedErr: errdefs.ErrFailedPrecondition,
},
{
name: "copy fails when size is negative",
name: "copy with unspecified size (zero)",
source: copySource{
reader: strings.NewReader("content"),
size: 0,
digest: digest.FromString("content"),
},
writer: fakeWriter{
Buffer: &bytes.Buffer{},
},
expected: "content",
},
{
name: "copy with unspecified size (-1)",
source: copySource{
reader: strings.NewReader("content"),
size: -1,
digest: digest.FromString("content"),
},
writer: fakeWriter{
Buffer: &bytes.Buffer{},
},
expected: "content",
},
{
name: "copy with invalid negative size",
source: copySource{
reader: strings.NewReader("content"),
size: -2,
},
writer: fakeWriter{
Buffer: &bytes.Buffer{},
@@ -230,7 +254,9 @@ func TestCopy(t *testing.T) {
assert.ErrorIs(t, err, testcase.expectedErr)
return
}
if testcase.source.size == -1 {
assert.Zero(t, testcase.writer.committedSize)
}
assert.NoError(t, err)
assert.Equal(t, testcase.source.digest, testcase.writer.committedDigest)
assert.Equal(t, testcase.expected, testcase.writer.String())
@@ -273,6 +299,7 @@ type commitFunction func() error
type fakeWriter struct {
*bytes.Buffer
committedSize int64
committedDigest digest.Digest
status Status
commitFunc commitFunction
@@ -284,6 +311,7 @@ func (f *fakeWriter) Close() error {
}
func (f *fakeWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...Opt) error {
f.committedSize = size
f.committedDigest = expected
if f.commitFunc == nil {
return nil