mirror of
https://github.com/pgsty/minio.git
synced 2026-08-09 07:43:29 +03:00
fix(storage): reject unusable erasure metadata at every sink
Malformed erasure layouts can divide by zero, while negative part sizes collapse expected shard sizes to zero and make truncated data appear healthy. Boundary validation alone is insufficient because poisoned metadata may already exist on disk or arrive through local heal paths. Reject non-positive block sizes at the sole Erasure constructor, guard the metadata arithmetic helpers and rebalance calculation, refuse negative part sizes before persistence, and make CheckParts and VerifyFile reject previously stored poison. Tests cover both shard-size implementations, construction, persistence, local verification, and the wire boundary. Co-authored-by: ChatGPT <noreply@openai.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,17 @@ func NewErasure(ctx context.Context, dataBlocks, parityBlocks int, blockSize int
|
||||
return e, reedsolomon.ErrInvShardNum
|
||||
}
|
||||
|
||||
// blockSize reaches here from FileInfo.Erasure, i.e. from xl.meta, which a
|
||||
// peer can write, and FileInfo.IsValid() does not check it. A coder with a
|
||||
// non-positive block size cannot encode or decode anything, so refusing to
|
||||
// build one loses nothing -- but building one leaves every division by
|
||||
// e.blockSize downstream (ShardFileSize, ShardFileOffset, and the whole of
|
||||
// erasure-decode.go) as an integer divide-by-zero. Reject at the single
|
||||
// point where every Erasure value in the process is constructed.
|
||||
if blockSize <= 0 {
|
||||
return e, errInvalidArgument
|
||||
}
|
||||
|
||||
if dataBlocks+parityBlocks > 256 {
|
||||
return e, reedsolomon.ErrMaxShardNum
|
||||
}
|
||||
@@ -125,6 +136,13 @@ func (e *Erasure) ShardFileSize(totalLength int64) int64 {
|
||||
if totalLength == -1 {
|
||||
return -1
|
||||
}
|
||||
// NewErasure validates dataBlocks and parityBlocks but not blockSize, and
|
||||
// the values reach it from FileInfo.Erasure - i.e. from xl.meta, which a
|
||||
// peer can write. Mirrors the guard on ErasureInfo.ShardFileSize; without
|
||||
// it a zero block size is an integer divide-by-zero here instead.
|
||||
if e.blockSize <= 0 || e.dataBlocks <= 0 {
|
||||
return 0
|
||||
}
|
||||
numShards := totalLength / e.blockSize
|
||||
lastBlockSize := totalLength % e.blockSize
|
||||
lastShardSize := ceilFrac(lastBlockSize, int64(e.dataBlocks))
|
||||
|
||||
Reference in New Issue
Block a user