Small bug, but still...
naddy@ reported a double free when interrupting (^C) ftp(1) at the end
or url_get(). If that happens, the SIGINT handler longjmps and the
cleanup path is taken a second time. To avoid this, restore the
previous SIGINT handler in each possible error path. I chose to restore
it earlier in the successful path to avoid too much duplication.
file_get() gets the same treatment.
Note that naddy hit this because of another bug causing ftp_close()
to stall, and this depends on the server you're talking to. You can
insert a sleep(10); call before "return (rval);" to help reproduce the
crash.
ok?
Index: fetch.c
===================================================================
RCS file: /d/cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.195
diff -u -p -p -u -r1.195 fetch.c
--- fetch.c 20 Jun 2020 09:59:48 -0000 1.195
+++ fetch.c 21 Jun 2020 00:12:10 -0000
@@ -261,6 +261,7 @@ file_get(const char *path, const char *o
for (cp = buf; len > 0; len -= wlen, cp += wlen) {
if ((wlen = write(out, cp, len)) == -1) {
warn("Writing %s", savefile);
+ signal(SIGINT, oldintr);
signal(SIGINFO, oldinti);
goto cleanup_copy;
}
@@ -274,6 +275,7 @@ file_get(const char *path, const char *o
}
}
save_errno = errno;
+ signal(SIGINT, oldintr);
signal(SIGINFO, oldinti);
if (hash && !progress && bytes > 0) {
if (bytes < mark)
@@ -288,7 +290,6 @@ file_get(const char *path, const char *o
progressmeter(1, NULL);
if (verbose)
ptransfer(0);
- (void)signal(SIGINT, oldintr);
rval = 0;
@@ -1032,6 +1033,7 @@ noslash:
oldinti = signal(SIGINFO, psummary);
if (chunked) {
error = save_chunked(fin, tls, out, buf, buflen);
+ signal(SIGINT, oldintr);
signal(SIGINFO, oldinti);
if (error == -1)
goto cleanup_url_get;
@@ -1041,6 +1043,7 @@ noslash:
for (cp = buf; len > 0; len -= wlen, cp += wlen) {
if ((wlen = write(out, cp, len)) == -1) {
warn("Writing %s", savefile);
+ signal(SIGINT, oldintr);
signal(SIGINFO, oldinti);
goto cleanup_url_get;
}
@@ -1054,6 +1057,7 @@ noslash:
}
}
save_errno = errno;
+ signal(SIGINT, oldintr);
signal(SIGINFO, oldinti);
if (hash && !progress && bytes > 0) {
if (bytes < mark)
@@ -1080,7 +1084,6 @@ noslash:
if (verbose)
ptransfer(0);
- (void)signal(SIGINT, oldintr);
rval = 0;
goto cleanup_url_get;
--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE