New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bufio: add comment on broken underlying readers #49795
Comments
Could you build a minimal reproducer with the function in question? I would agree it shoudn't crash looking at https://pkg.go.dev/io#ReadFull |
@andig Still trying, I will update here ASAP. |
In case it helps, in similar issues in the past it seems like the panic might have been due to concurrent Read calls to the bufio.Reader. |
@nishanths Thanks, that's the first thing came into my mind, I will double-check that. |
Finally, I figured it out, it was caused by an invalid implementation of // Read implements the net.Conn interface.
func (c *conn) Read(byt []byte) (int, error) {
var buf []byte
var ok bool
if !c.readDeadline.IsZero() {
readTimer := time.NewTimer(time.Until(c.readDeadline))
defer readTimer.Stop()
select {
case <-readTimer.C:
return 0, errTimeout
case buf, ok = <-c.read:
}
} else {
buf, ok = <-c.read
}
if !ok {
return 0, errTerminated
}
copy(byt, buf)
c.listener.readDone <- struct{}{}
return len(buf), nil
} This function returns the length of On the other hand, func (b *Reader) Read(p []byte) (n int, err error) {
n = len(p)
if n == 0 {
if b.Buffered() > 0 {
return 0, nil
}
return 0, b.readErr()
}
if b.r == b.w {
if b.err != nil {
return 0, b.readErr()
}
if len(p) >= len(b.buf) {
// Large read, empty buffer.
// Read directly into p to avoid copy.
n, b.err = b.rd.Read(p)
if n < 0 {
panic(errNegativeRead)
}
if n > 0 {
b.lastByte = int(p[n-1])
b.lastRuneSize = -1
}
return n, b.readErr()
}
// One read.
// Do not use b.fill, which will loop.
b.r = 0
b.w = 0
n, b.err = b.rd.Read(b.buf)
if n < 0 {
panic(errNegativeRead)
}
if n == 0 {
return 0, b.readErr()
}
b.w += n
}
// copy as much as we can
n = copy(p, b.buf[b.r:b.w])
b.r += n
b.lastByte = int(b.buf[b.r-1])
b.lastRuneSize = -1
return n, nil
} For my case, I will fix the invalid implementation of |
We don't generally try to defend against misbehaving All that said, I think we could do something here. Maybe just a comment on the line with |
Change https://golang.org/cl/367214 mentions this issue: |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?Running on Ubuntu 20.04.2 LTS AMD64
go env
OutputWhat did you do?
I'm using gomavlib: https://github.com/aler9/gomavlib to build a server process , but find out some server crash like this:
The code in gomavlib causing the problem is :
The bufio.Reader is created with a size of 512, how can we copy with a byte array index value 987?
I have already built the process using -race and found no data race report. From my point of view, io.ReadFull is not supposed to crash on this scenario, that's why I fire an issue here.
But I can't reproduce it right now, I'm still trying to figure out what might cause this, any clues and suggestions are welcome.
What did you expect to see?
Expect the process not to crash.
What did you see instead?
Process crash on some situation.
The text was updated successfully, but these errors were encountered: