mirror of
https://github.com/golang/go
synced 2024-11-25 13:07:57 -07:00
io: prevent ReadAtLeast spinloop if min > len(buf)
R=r, heresy.mc CC=golang-dev https://golang.org/cl/2017042
This commit is contained in:
parent
d125faeed0
commit
4642708984
@ -19,6 +19,9 @@ type Error struct {
|
||||
// but failed to return an explicit error.
|
||||
var ErrShortWrite os.Error = &Error{"short write"}
|
||||
|
||||
// ErrShortBuffer means that a read required a longer buffer than was provided.
|
||||
var ErrShortBuffer os.Error = &Error{"short buffer"}
|
||||
|
||||
// ErrUnexpectedEOF means that os.EOF was encountered in the
|
||||
// middle of reading a fixed-size block or data structure.
|
||||
var ErrUnexpectedEOF os.Error = &Error{"unexpected EOF"}
|
||||
@ -165,8 +168,11 @@ func WriteString(w Writer, s string) (n int, err os.Error) {
|
||||
// The error is os.EOF only if no bytes were read.
|
||||
// If an EOF happens after reading fewer than min bytes,
|
||||
// ReadAtLeast returns ErrUnexpectedEOF.
|
||||
// If min is greater than the length of buf, ReadAtLeast returns ErrShortBuffer.
|
||||
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) {
|
||||
n = 0
|
||||
if len(buf) < min {
|
||||
return 0, ErrShortBuffer
|
||||
}
|
||||
for n < min {
|
||||
nn, e := r.Read(buf[n:])
|
||||
if nn > 0 {
|
||||
@ -179,7 +185,7 @@ func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) {
|
||||
return n, e
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
return
|
||||
}
|
||||
|
||||
// ReadFull reads exactly len(buf) bytes from r into buf.
|
||||
|
@ -7,6 +7,7 @@ package io_test
|
||||
import (
|
||||
"bytes"
|
||||
. "io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -78,3 +79,42 @@ func TestCopynWriteTo(t *testing.T) {
|
||||
t.Errorf("Copyn did not work properly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadAtLeast(t *testing.T) {
|
||||
var rb bytes.Buffer
|
||||
rb.Write([]byte("0123"))
|
||||
buf := make([]byte, 2)
|
||||
n, err := ReadAtLeast(&rb, buf, 2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
n, err = ReadAtLeast(&rb, buf, 4)
|
||||
if err != ErrShortBuffer {
|
||||
t.Errorf("expected ErrShortBuffer got %v", err)
|
||||
}
|
||||
if n != 0 {
|
||||
t.Errorf("expected to have read 0 bytes, got %v", n)
|
||||
}
|
||||
n, err = ReadAtLeast(&rb, buf, 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if n != 2 {
|
||||
t.Errorf("expected to have read 2 bytes, got %v", n)
|
||||
}
|
||||
n, err = ReadAtLeast(&rb, buf, 2)
|
||||
if err != os.EOF {
|
||||
t.Errorf("expected EOF, got %v", err)
|
||||
}
|
||||
if n != 0 {
|
||||
t.Errorf("expected to have read 0 bytes, got %v", n)
|
||||
}
|
||||
rb.Write([]byte("4"))
|
||||
n, err = ReadAtLeast(&rb, buf, 2)
|
||||
if err != ErrUnexpectedEOF {
|
||||
t.Errorf("expected ErrUnexpectedEOF, got %v", err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("expected to have read 1 bytes, got %v", n)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user