mirror of
https://github.com/golang/go
synced 2024-11-25 15:17:58 -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.
|
// but failed to return an explicit error.
|
||||||
var ErrShortWrite os.Error = &Error{"short write"}
|
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
|
// ErrUnexpectedEOF means that os.EOF was encountered in the
|
||||||
// middle of reading a fixed-size block or data structure.
|
// middle of reading a fixed-size block or data structure.
|
||||||
var ErrUnexpectedEOF os.Error = &Error{"unexpected EOF"}
|
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.
|
// The error is os.EOF only if no bytes were read.
|
||||||
// If an EOF happens after reading fewer than min bytes,
|
// If an EOF happens after reading fewer than min bytes,
|
||||||
// ReadAtLeast returns ErrUnexpectedEOF.
|
// 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) {
|
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 {
|
for n < min {
|
||||||
nn, e := r.Read(buf[n:])
|
nn, e := r.Read(buf[n:])
|
||||||
if nn > 0 {
|
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, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFull reads exactly len(buf) bytes from r into buf.
|
// ReadFull reads exactly len(buf) bytes from r into buf.
|
||||||
|
@ -7,6 +7,7 @@ package io_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
. "io"
|
. "io"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -78,3 +79,42 @@ func TestCopynWriteTo(t *testing.T) {
|
|||||||
t.Errorf("Copyn did not work properly")
|
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