diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index 4646d491b..035fa456c 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -126,6 +126,9 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d if err != nil { return oi, toObjectErr(err, srcBucket, srcObject) } + if err := checkObjectGenerationQuorum(fi, metaArr, errs); err != nil { + return oi, toObjectErr(err, srcBucket, srcObject) + } if fi.Deleted { if srcOpts.VersionID == "" { return oi, toObjectErr(errFileNotFound, srcBucket, srcObject) diff --git a/cmd/erasure-read-generation_test.go b/cmd/erasure-read-generation_test.go index 5a2ee2ea4..33cb2b1bd 100644 --- a/cmd/erasure-read-generation_test.go +++ b/cmd/erasure-read-generation_test.go @@ -136,6 +136,12 @@ func TestPoolsReadGenerationConflictDoesNotExposeOldValue(t *testing.T) { } if tc.mode != "newer-quorum" { for _, version := range []string{"", nullVersionID} { + _, err := set.CopyObject(ctx, bucket, object, bucket, object, + ObjectInfo{metadataOnly: true, UserDefined: map[string]string{"copy-test": "conflicting-source"}}, + ObjectOptions{VersionID: version}, ObjectOptions{}) + if !isErrReadQuorum(err) { + t.Errorf("COPY-to-self version=%q: want read-quorum error, got %v", version, err) + } for _, scan := range []madmin.HealScanMode{madmin.HealNormalScan, madmin.HealDeepScan} { _, err := set.HealObject(ctx, bucket, object, version, madmin.HealOpts{ScanMode: scan, Remove: true}) if !isErrReadQuorum(err) {