mirror of
https://github.com/pgsty/minio.git
synced 2026-10-31 04:50:40 +03:00
fix: report logical part sizes in GetObjectAttributes
GetObjectAttributes filled ObjectPart.Size from the on-disk part length (cmd/object-handlers.go:715), so every compressed or encrypted multipart object reported transformed sizes that do not sum to the logical ObjectSize the same response returns from objInfo.GetActualSize(). Report each part's uploaded plaintext length instead: a compressed part uses its recorded ActualSize, and a separately encrypted part derives the plaintext length with sio.DecryptedSize, because ActualSize is the ciphertext length for a replicated SSE-C part and zero for parts written before actualSize existed. Only parts of an encrypted multipart object are streams of their own. A legacy encrypted object carries no multipart marker and is one continuous stream that the erasure writer split into storage fragments, so those fragments keep their stored size. Where a part is a stream, one whose length cannot be a valid encrypted stream has no logical length, and the request now fails with XMinioObjectTampered rather than reporting the ciphertext length; DecryptObjectInfo does not catch that case, because ObjectInfo.isMultipart gives up on the first bad part and only the object total is then validated. Tests: TestAPIGetObjectAttributesMultipartLogicalPartSize (plain, compressed, SSE-C and compressed+SSE-C, consecutive and sparse part numbers), TestAPIGetObjectAttributesCompressedEmptyTrailingPart, TestAPIGetObjectAttributesEncryptedPartLengths, and a part-size assertion added to TestAPISSECMultipartReplicationTrust. Compatibility: the XML shape is unchanged and nothing is written to disk, only the value of the existing Size element is corrected. Fixes pgsty/silo#114 Signed-off-by: Feng Ruohang <rh@vonng.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L7qJqWwy8oFA6aCXWRzXQe
This commit is contained in:
@@ -829,6 +829,25 @@ func testAPISSECMultipartReplicationTrust(obj ObjectLayer, instanceType, bucketN
|
||||
if !bytes.Equal(getRec.Body.Bytes(), data) {
|
||||
t.Fatal("replicated SSE-C multipart object did not decrypt to source plaintext")
|
||||
}
|
||||
|
||||
// A replicated SSE-C part is written as raw ciphertext, so its stored
|
||||
// ActualSize is the ciphertext length. GetObjectAttributes must still
|
||||
// report the part's plaintext length, which for this single-part object
|
||||
// is the whole object size.
|
||||
attributes := attributesPartsFetch(t, apiRouter, credentials, bucketName, object, sseHeaders)
|
||||
if len(attributes.ObjectParts.Parts) != 1 {
|
||||
t.Fatalf("replica attributes part count %d, want 1", len(attributes.ObjectParts.Parts))
|
||||
}
|
||||
if got := attributes.ObjectParts.Parts[0].Size; got != int64(len(data)) {
|
||||
t.Errorf("replica attributes part 1 size=%d, want plaintext size %d", got, len(data))
|
||||
}
|
||||
if attributes.ObjectSize != int64(len(data)) {
|
||||
t.Errorf("replica attributes ObjectSize=%d, want %d", attributes.ObjectSize, len(data))
|
||||
}
|
||||
if attributes.ObjectParts.Parts[0].Size != attributes.ObjectSize {
|
||||
t.Errorf("replica attributes part 1 size=%d does not match ObjectSize=%d",
|
||||
attributes.ObjectParts.Parts[0].Size, attributes.ObjectSize)
|
||||
}
|
||||
}
|
||||
|
||||
// TestAPIStreamingTrailerWithUntrustedReplicationHeaders verifies that a
|
||||
|
||||
Reference in New Issue
Block a user