summaryrefslogtreecommitdiffstats
path: root/usr.bin/fetch
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2012-01-18 15:13:21 +0000
committerdes <des@FreeBSD.org>2012-01-18 15:13:21 +0000
commit939a66af62dc031d0ca35b5e7b1410f8aedc1d7c (patch)
treea2005365ba56694fd925cd9d8f2687ea003a376f /usr.bin/fetch
parent7972e45b2052402d891e3dd144472547dac25ec6 (diff)
downloadFreeBSD-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 'usr.bin/fetch')
-rw-r--r--usr.bin/fetch/fetch.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c
index 8d26671..e8b7318 100644
--- a/usr.bin/fetch/fetch.c
+++ b/usr.bin/fetch/fetch.c
@@ -317,7 +317,7 @@ fetch(char *URL, const char *path)
struct stat sb, nsb;
struct xferstat xs;
FILE *f, *of;
- size_t size, wr;
+ size_t size, readcnt, wr;
off_t count;
char flags[8];
const char *slash;
@@ -636,21 +636,26 @@ fetch(char *URL, const char *path)
stat_end(&xs);
siginfo = 0;
}
- if ((size = fread(buf, 1, size, f)) == 0) {
+
+ if (size == 0)
+ break;
+
+ if ((readcnt = fread(buf, 1, size, f)) < size) {
if (ferror(f) && errno == EINTR && !sigint)
clearerr(f);
- else
+ else if (readcnt == 0)
break;
}
- stat_update(&xs, count += size);
- for (ptr = buf; size > 0; ptr += wr, size -= wr)
- if ((wr = fwrite(ptr, 1, size, of)) < size) {
+
+ stat_update(&xs, count += readcnt);
+ for (ptr = buf; readcnt > 0; ptr += wr, readcnt -= wr)
+ if ((wr = fwrite(ptr, 1, readcnt, of)) < readcnt) {
if (ferror(of) && errno == EINTR && !sigint)
clearerr(of);
else
break;
}
- if (size != 0)
+ if (readcnt != 0)
break;
}
if (!sigalrm)
OpenPOWER on IntegriCloud