diff options
author | des <des@FreeBSD.org> | 2012-01-18 15:13:21 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2012-01-18 15:13:21 +0000 |
commit | 939a66af62dc031d0ca35b5e7b1410f8aedc1d7c (patch) | |
tree | a2005365ba56694fd925cd9d8f2687ea003a376f /lib/libfetch/http.c | |
parent | 7972e45b2052402d891e3dd144472547dac25ec6 (diff) | |
download | FreeBSD-src-939a66af62dc031d0ca35b5e7b1410f8aedc1d7c.zip FreeBSD-src-939a66af62dc031d0ca35b5e7b1410f8aedc1d7c.tar.gz |
Fix two issues related to the use of SIGINFO in fetch(1) to display
progress information. The first is that fetch_read() (used in the HTTP
code but not the FTP code) can enter an infinite loop if it has previously
been interrupted by a signal. The second is that when it is interrupted,
fetch_read() will discard any data it may have read up to that point.
Luckily, both bugs are extremely timing-sensitive and therefore difficult
to trigger.
PR: bin/153240
Submitted by: Mark <markjdb@gmail.com>
MFC after: 3 weeks
Diffstat (limited to 'lib/libfetch/http.c')
-rw-r--r-- | lib/libfetch/http.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c index b33d6f1..557ff26 100644 --- a/lib/libfetch/http.c +++ b/lib/libfetch/http.c @@ -196,6 +196,8 @@ http_growbuf(struct httpio *io, size_t len) static int http_fillbuf(struct httpio *io, size_t len) { + ssize_t nbytes; + if (io->error) return (-1); if (io->eof) @@ -204,10 +206,11 @@ http_fillbuf(struct httpio *io, size_t len) if (io->chunked == 0) { if (http_growbuf(io, len) == -1) return (-1); - if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) { - io->error = 1; + if ((nbytes = fetch_read(io->conn, io->buf, len)) == -1) { + io->error = errno; return (-1); } + io->buflen = nbytes; io->bufpos = 0; return (io->buflen); } @@ -227,10 +230,11 @@ http_fillbuf(struct httpio *io, size_t len) len = io->chunksize; if (http_growbuf(io, len) == -1) return (-1); - if ((io->buflen = fetch_read(io->conn, io->buf, len)) == -1) { - io->error = 1; + if ((nbytes = fetch_read(io->conn, io->buf, len)) == -1) { + io->error = errno; return (-1); } + io->buflen = nbytes; io->chunksize -= io->buflen; if (io->chunksize == 0) { @@ -272,8 +276,11 @@ http_readfn(void *v, char *buf, int len) io->bufpos += l; } - if (!pos && io->error) + if (!pos && io->error) { + if (io->error == EINTR) + io->error = 0; return (-1); + } return (pos); } |