gomodule / redigo

Go client for Redis
Apache License 2.0
9.76k stars 1.25k forks source link

buffio.Write may write less bytes than requested #648

Closed szmcdull closed 1 year ago

szmcdull commented 1 year ago

buffio.Write may write less bytes than requested. But conn.writeXXX is not aware of this

// Write writes the contents of p into the buffer.
// It returns the number of bytes written.
// If nn < len(p), it also returns an error explaining
// why the write is short.
func (b *Writer) Write(p []byte) (nn int, err error) {
    for len(p) > b.Available() && b.err == nil {
        var n int
        if b.Buffered() == 0 {
            // Large write, empty buffer.
            // Write directly from p to avoid copy.
            n, b.err = b.wr.Write(p)
        } else {
            n = copy(b.buf[b.n:], p)
            b.n += n
            b.Flush()
        }
        nn += n
        p = p[n:]
    }
    if b.err != nil {
        return nn, b.err
    }
    n := copy(b.buf[b.n:], p)
    b.n += n
    nn += n
    return nn, nil
}
func (c *conn) writeBytes(p []byte) error {
    if err := c.writeLen('$', len(p)); err != nil {
        return err
    }
    if _, err := c.bw.Write(p); err != nil {
        return err
    }
    _, err := c.bw.WriteString("\r\n")
    return err
}
stevenh commented 1 year ago

While it doesn't pay attention to the number of bytes written it will return an error, which will allow the connection to be cleaned up as needed. This is the only thing it can do as it wouldn't be safe to continue after the error.