mirror of
https://github.com/minio/minio.git
synced 2025-11-07 21:02:58 -05:00
Fix CreateFile shared buffer corruption. (#18652)
`(*xlStorageDiskIDCheck).CreateFile` wraps the incoming reader in `xioutil.NewDeadlineReader`. The wrapped reader is handed to `(*xlStorage).CreateFile`. This performs a Read call via `writeAllDirect`, which reads into an `ODirectPool` buffer. `(*DeadlineReader).Read` spawns an async read into the buffer. If a timeout is hit while reading, the read operation returns to `writeAllDirect`. The operation returns an error and the buffer is reused. However, if the async `Read` call unblocks, it will write to the now recycled buffer. Fix: Remove the `DeadlineReader` - it is inherently unsafe. Instead, rely on the network timeouts. This is not a disk timeout, anyway. Regression in https://github.com/minio/minio/pull/17745
This commit is contained in:
@@ -28,19 +28,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type sleepReader struct {
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func (r *sleepReader) Read(p []byte) (n int, err error) {
|
||||
time.Sleep(r.timeout)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (r *sleepReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type sleepWriter struct {
|
||||
timeout time.Duration
|
||||
}
|
||||
@@ -54,29 +41,6 @@ func (w *sleepWriter) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestDeadlineReader(t *testing.T) {
|
||||
r := NewDeadlineReader(&sleepReader{timeout: 500 * time.Millisecond}, 450*time.Millisecond)
|
||||
buf := make([]byte, 4)
|
||||
_, err := r.Read(buf)
|
||||
r.Close()
|
||||
if err != context.DeadlineExceeded {
|
||||
t.Errorf("DeadlineReader shouldn't be successful %v - should return context.DeadlineExceeded", err)
|
||||
}
|
||||
_, err = r.Read(buf)
|
||||
if err != context.DeadlineExceeded {
|
||||
t.Errorf("DeadlineReader shouldn't be successful %v - should return context.DeadlineExceeded", err)
|
||||
}
|
||||
r = NewDeadlineReader(&sleepReader{timeout: 100 * time.Millisecond}, 600*time.Millisecond)
|
||||
n, err := r.Read(buf)
|
||||
r.Close()
|
||||
if err != nil {
|
||||
t.Errorf("DeadlineReader should succeed but failed with %s", err)
|
||||
}
|
||||
if n != 4 {
|
||||
t.Errorf("DeadlineReader should succeed but should have only read 4 bytes, but returned %d instead", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeadlineWriter(t *testing.T) {
|
||||
w := NewDeadlineWriter(&sleepWriter{timeout: 500 * time.Millisecond}, 450*time.Millisecond)
|
||||
_, err := w.Write([]byte("1"))
|
||||
|
||||
Reference in New Issue
Block a user