mirror of
https://github.com/moparisthebest/curl
synced 2024-11-16 14:35:03 -05:00
multi: avoid double-free
Curl_follow() no longer frees the string. Make sure it happens in the caller function, like we normally handle allocations. This bug was introduced with the use of the URL API internally, it has never been in a release version Reported-by: Dario Weißer Closes #3149
This commit is contained in:
parent
8a49f91d32
commit
05564e750e
13
lib/multi.c
13
lib/multi.c
@ -1707,7 +1707,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
char *newurl = NULL;
|
char *newurl = NULL;
|
||||||
followtype follow = FOLLOW_NONE;
|
followtype follow = FOLLOW_NONE;
|
||||||
CURLcode drc;
|
CURLcode drc;
|
||||||
bool retry = FALSE;
|
|
||||||
|
|
||||||
drc = Curl_retry_request(data->easy_conn, &newurl);
|
drc = Curl_retry_request(data->easy_conn, &newurl);
|
||||||
if(drc) {
|
if(drc) {
|
||||||
@ -1715,19 +1714,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
result = drc;
|
result = drc;
|
||||||
stream_error = TRUE;
|
stream_error = TRUE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
retry = (newurl)?TRUE:FALSE;
|
|
||||||
|
|
||||||
Curl_posttransfer(data);
|
Curl_posttransfer(data);
|
||||||
drc = multi_done(&data->easy_conn, result, FALSE);
|
drc = multi_done(&data->easy_conn, result, FALSE);
|
||||||
|
|
||||||
/* When set to retry the connection, we must to go back to
|
/* When set to retry the connection, we must to go back to
|
||||||
* the CONNECT state */
|
* the CONNECT state */
|
||||||
if(retry) {
|
if(newurl) {
|
||||||
if(!drc || (drc == CURLE_SEND_ERROR)) {
|
if(!drc || (drc == CURLE_SEND_ERROR)) {
|
||||||
follow = FOLLOW_RETRY;
|
follow = FOLLOW_RETRY;
|
||||||
drc = Curl_follow(data, newurl, follow);
|
drc = Curl_follow(data, newurl, follow);
|
||||||
newurl = NULL; /* freed by Curl_follow() */
|
|
||||||
if(!drc) {
|
if(!drc) {
|
||||||
multistate(data, CURLM_STATE_CONNECT);
|
multistate(data, CURLM_STATE_CONNECT);
|
||||||
rc = CURLM_CALL_MULTI_PERFORM;
|
rc = CURLM_CALL_MULTI_PERFORM;
|
||||||
@ -1987,16 +1983,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
else
|
else
|
||||||
follow = FOLLOW_RETRY;
|
follow = FOLLOW_RETRY;
|
||||||
result = multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
result = multi_done(&data->easy_conn, CURLE_OK, FALSE);
|
||||||
if(result)
|
if(!result) {
|
||||||
/* Curl_follow() would otherwise free this */
|
|
||||||
free(newurl);
|
|
||||||
else {
|
|
||||||
result = Curl_follow(data, newurl, follow);
|
result = Curl_follow(data, newurl, follow);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
multistate(data, CURLM_STATE_CONNECT);
|
multistate(data, CURLM_STATE_CONNECT);
|
||||||
rc = CURLM_CALL_MULTI_PERFORM;
|
rc = CURLM_CALL_MULTI_PERFORM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(newurl);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* after the transfer is done, go DONE */
|
/* after the transfer is done, go DONE */
|
||||||
@ -2008,6 +2002,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||||||
newurl = data->req.location;
|
newurl = data->req.location;
|
||||||
data->req.location = NULL;
|
data->req.location = NULL;
|
||||||
result = Curl_follow(data, newurl, FOLLOW_FAKE);
|
result = Curl_follow(data, newurl, FOLLOW_FAKE);
|
||||||
|
free(newurl);
|
||||||
if(result) {
|
if(result) {
|
||||||
stream_error = TRUE;
|
stream_error = TRUE;
|
||||||
result = multi_done(&data->easy_conn, result, TRUE);
|
result = multi_done(&data->easy_conn, result, TRUE);
|
||||||
|
@ -1458,6 +1458,8 @@ CURLcode Curl_posttransfer(struct Curl_easy *data)
|
|||||||
/*
|
/*
|
||||||
* Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
|
* Curl_follow() handles the URL redirect magic. Pass in the 'newurl' string
|
||||||
* as given by the remote server and set up the new URL to request.
|
* as given by the remote server and set up the new URL to request.
|
||||||
|
*
|
||||||
|
* This function DOES NOT FREE the given url.
|
||||||
*/
|
*/
|
||||||
CURLcode Curl_follow(struct Curl_easy *data,
|
CURLcode Curl_follow(struct Curl_easy *data,
|
||||||
char *newurl, /* the Location: string */
|
char *newurl, /* the Location: string */
|
||||||
@ -1515,7 +1517,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
|
|||||||
|
|
||||||
DEBUGASSERT(data->state.uh);
|
DEBUGASSERT(data->state.uh);
|
||||||
uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, 0);
|
uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl, 0);
|
||||||
free(newurl);
|
|
||||||
if(uc)
|
if(uc)
|
||||||
/* TODO: consider an error code remap here */
|
/* TODO: consider an error code remap here */
|
||||||
return CURLE_URL_MALFORMAT;
|
return CURLE_URL_MALFORMAT;
|
||||||
|
Loading…
Reference in New Issue
Block a user