webfs: reset readline Ibuf rp/wp to buf start when buffer drains
readline() in sys/src/cmd/webfs/buf.c reads response bytes
into the 4096-byte b->buf via ioread(..., b->wp,
sizeof(b->buf)/2). When b->rp catches up to b->wp, readline
treats the buffer as empty and issues another ioread but
never resets rp/wp. Over many drain/refill cycles the
pointers walk toward the end of b->buf, and the next ioread
overflows into the adjacent rp/wp fields of the same Ibuf
struct. The next *b->rp++ dereferences the corrupted
pointer and webfs faults inside readline.
Any webfs consumer driving sustained multi-connection reads
hangs on heavy pages. hget (single-connection, sequential)
does not cycle the buffer enough to trip it on the same URL.
Fix: reset rp and wp to &b->buf[0] each time the buffer is
consumed to empty. Single-line change. No behaviour change
for any input; the buffer was already semantically empty,
and initibuf / unreadline already reset rp/wp in their own
paths — this closes the third drain path (readline itself).
RFC relevance: none
--- sys/src/cmd/webfs/buf.c
+++ sys/src/cmd/webfs/buf.c
@@ -57,6 +57,7 @@
for(p = buf;;){
if(b->rp >= b->wp){
+ b->rp = b->wp = b->buf;
n = ioread(b->io, b->fd, b->wp, sizeof(b->buf)/2);
if(n < 0)
return -1;
|