aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--RELEASE-NOTES3
-rw-r--r--lib/multi.c19
-rw-r--r--lib/transfer.c24
-rw-r--r--lib/transfer.h4
5 files changed, 40 insertions, 15 deletions
diff --git a/CHANGES b/CHANGES
index 650a36f7b..eccb1db19 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,11 @@
Changelog
Daniel Stenberg (21 Aug 2009)
+- Andre Guibert de Bruet pointed out a missing return code check for a
+ strdup() that could lead to segfault if it returned NULL. I extended his
+ suggest patch to now have Curl_retry_request() return a regular return code
+ and better check that.
+
- Lots of good work by Krister Johansen, mostly related to pipelining:
Fix SIGSEGV on free'd easy_conn when pipe unexpectedly breaks
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 5af32e16a..77401bbe5 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -18,6 +18,7 @@ This release includes the following bugfixes:
o SIGSEGV when pipelined pipe unexpectedly breaks
o data corruption issue with re-connected transfers
o use after free if we're completed but easy_conn not NULL (pipelined)
+ o missing strdup() return code check
This release includes the following known bugs:
@@ -26,6 +27,6 @@ This release includes the following known bugs:
This release would not have looked like this without help, code, reports and
advice from friends like these:
- Karl Moerder, Kamil Dudka, Krister Johansen,
+ Karl Moerder, Kamil Dudka, Krister Johansen, Andre Guibert de Bruet
Thanks! (and sorry if I forgot to mention someone)
diff --git a/lib/multi.c b/lib/multi.c
index 1099b525d..686372ad1 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -1183,7 +1183,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
char *newurl;
followtype follow=FOLLOW_NONE;
CURLcode drc;
- bool retry = Curl_retry_request(easy->easy_conn, &newurl);
+ bool retry = FALSE;
+
+ drc = Curl_retry_request(easy->easy_conn, &newurl);
+ if(drc) {
+ /* a failure here pretty much implies an out of memory */
+ easy->result = drc;
+ disconnect_conn = TRUE;
+ }
+ else
+ retry = newurl?TRUE:FALSE;
Curl_posttransfer(easy->easy_handle);
drc = Curl_done(&easy->easy_conn, easy->result, FALSE);
@@ -1370,9 +1379,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else if(TRUE == done) {
char *newurl;
- bool retry = Curl_retry_request(easy->easy_conn, &newurl);
+ bool retry = FALSE;
followtype follow=FOLLOW_NONE;
+ easy->result = Curl_retry_request(easy->easy_conn, &newurl);
+ if(!easy->result)
+ retry = newurl?TRUE:FALSE;
+
/* call this even if the readwrite function returned error */
Curl_posttransfer(easy->easy_handle);
@@ -1406,7 +1419,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(easy, CURLM_STATE_CONNECT);
result = CURLM_CALL_MULTI_PERFORM;
}
- else
+ else if(newurl)
/* Since we "took it", we are in charge of freeing this on
failure */
free(newurl);
diff --git a/lib/transfer.c b/lib/transfer.c
index e5ba279d0..5bd742f47 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -2550,19 +2550,20 @@ Curl_reconnect_request(struct connectdata **connp)
return result;
}
-/* Returns TRUE and sets '*url' if a request retry is wanted.
+/* Returns CURLE_OK *and* sets '*url' if a request retry is wanted.
NOTE: that the *url is malloc()ed. */
-bool Curl_retry_request(struct connectdata *conn,
- char **url)
+CURLcode Curl_retry_request(struct connectdata *conn,
+ char **url)
{
- bool retry = FALSE;
struct SessionHandle *data = conn->data;
+ *url = NULL;
+
/* if we're talking upload, we can't do the checks below, unless the protocol
is HTTP as when uploading over HTTP we will still get a response */
if(data->set.upload && !(conn->protocol&PROT_HTTP))
- return retry;
+ return CURLE_OK;
if((data->req.bytecount +
data->req.headerbytecount == 0) &&
@@ -2574,6 +2575,8 @@ bool Curl_retry_request(struct connectdata *conn,
it again. Bad luck. Retry the same request on a fresh connect! */
infof(conn->data, "Connection died, retrying a fresh connect\n");
*url = strdup(conn->data->change.url);
+ if(!*url)
+ return CURLE_OUT_OF_MEMORY;
conn->bits.close = TRUE; /* close this connection */
conn->bits.retry = TRUE; /* mark this as a connection we're about
@@ -2581,10 +2584,8 @@ bool Curl_retry_request(struct connectdata *conn,
prevent i.e HTTP transfers to return
error just because nothing has been
transfered! */
- retry = TRUE;
}
-
- return retry;
+ return CURLE_OK;
}
/*
@@ -2629,7 +2630,12 @@ CURLcode Curl_perform(struct SessionHandle *data)
if(res == CURLE_OK) {
res = Transfer(conn); /* now fetch that URL please */
if((res == CURLE_OK) || (res == CURLE_RECV_ERROR)) {
- bool retry = Curl_retry_request(conn, &newurl);
+ bool retry = FALSE;
+ CURLcode rc = Curl_retry_request(conn, &newurl);
+ if(rc)
+ res = rc;
+ else
+ retry = newurl?TRUE:FALSE;
if(retry) {
res = CURLE_OK;
diff --git a/lib/transfer.h b/lib/transfer.h
index 4b39faa18..a9b1cd370 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@ int Curl_single_getsock(const struct connectdata *conn,
CURLcode Curl_readrewind(struct connectdata *conn);
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
CURLcode Curl_reconnect_request(struct connectdata **connp);
-bool Curl_retry_request(struct connectdata *conn, char **url);
+CURLcode Curl_retry_request(struct connectdata *conn, char **url);
/* This sets up a forthcoming transfer */
CURLcode