Fixed a memory leak when specifying a proxy with a file: URL and added
test case 288 to verify it.
This commit is contained in:
parent
b7131009fb
commit
0dd1219668
2
CHANGES
2
CHANGES
@ -16,6 +16,8 @@ Dan F (23 March 2007)
|
|||||||
- Added test harness infrastructure to support scp/sftp tests, using
|
- Added test harness infrastructure to support scp/sftp tests, using
|
||||||
OpenSSH as the server.
|
OpenSSH as the server.
|
||||||
|
|
||||||
|
- Fixed a memory leak when specifying a proxy with a file: URL.
|
||||||
|
|
||||||
Yang Tse (20 March 2007)
|
Yang Tse (20 March 2007)
|
||||||
- Fixed: When a signal was caught awaiting for an event using Curl_select()
|
- Fixed: When a signal was caught awaiting for an event using Curl_select()
|
||||||
or Curl_poll() with a non-zero timeout both functions would restart the
|
or Curl_poll() with a non-zero timeout both functions would restart the
|
||||||
|
129
lib/url.c
129
lib/url.c
@ -2767,8 +2767,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
char passwd[MAX_CURL_PASSWORD_LENGTH];
|
char passwd[MAX_CURL_PASSWORD_LENGTH];
|
||||||
int rc;
|
int rc;
|
||||||
bool reuse;
|
bool reuse;
|
||||||
char *proxy;
|
char *proxy = NULL;
|
||||||
bool proxy_alloc = FALSE;
|
|
||||||
|
|
||||||
#ifndef USE_ARES
|
#ifndef USE_ARES
|
||||||
#ifdef SIGALRM
|
#ifdef SIGALRM
|
||||||
@ -2821,7 +2820,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
conn->bits.proxy = (bool)(data->set.proxy && *data->set.proxy);
|
conn->bits.proxy = (bool)(data->set.proxy && *data->set.proxy);
|
||||||
conn->bits.httpproxy = (bool)(conn->bits.proxy
|
conn->bits.httpproxy = (bool)(conn->bits.proxy
|
||||||
&& (conn->proxytype == CURLPROXY_HTTP));
|
&& (conn->proxytype == CURLPROXY_HTTP));
|
||||||
proxy = data->set.proxy; /* if global proxy is set, this is it */
|
|
||||||
|
|
||||||
/* Default protocol-independent behavior doesn't support persistent
|
/* Default protocol-independent behavior doesn't support persistent
|
||||||
connections, so we set this to force-close. Protocols that support
|
connections, so we set this to force-close. Protocols that support
|
||||||
@ -2917,6 +2916,15 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->set.proxy) {
|
||||||
|
proxy = strdup(data->set.proxy); /* if global proxy is set, this is it */
|
||||||
|
if(NULL == proxy) {
|
||||||
|
failf(data, "memory shortage");
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* proxy must be freed later unless NULL */
|
||||||
|
|
||||||
#ifndef CURL_DISABLE_HTTP
|
#ifndef CURL_DISABLE_HTTP
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Detect what (if any) proxy to use. Remember that this selects a host
|
* Detect what (if any) proxy to use. Remember that this selects a host
|
||||||
@ -3018,8 +3026,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
if(proxy && *proxy) {
|
if(proxy && *proxy) {
|
||||||
long bits = conn->protocol & (PROT_HTTPS|PROT_SSL|PROT_MISSING);
|
long bits = conn->protocol & (PROT_HTTPS|PROT_SSL|PROT_MISSING);
|
||||||
|
|
||||||
proxy_alloc=TRUE; /* this needs to be freed later */
|
|
||||||
|
|
||||||
if(conn->proxytype == CURLPROXY_HTTP) {
|
if(conn->proxytype == CURLPROXY_HTTP) {
|
||||||
/* force this connection's protocol to become HTTP */
|
/* force this connection's protocol to become HTTP */
|
||||||
conn->protocol = PROT_HTTP | bits;
|
conn->protocol = PROT_HTTP | bits;
|
||||||
@ -3044,35 +3050,16 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
|
|
||||||
reurl = aprintf("%s://%s", conn->protostr, data->change.url);
|
reurl = aprintf("%s://%s", conn->protostr, data->change.url);
|
||||||
|
|
||||||
if(!reurl)
|
if(!reurl) {
|
||||||
|
Curl_safefree(proxy);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
data->change.url = reurl;
|
data->change.url = reurl;
|
||||||
data->change.url_alloc = TRUE; /* free this later */
|
data->change.url_alloc = TRUE; /* free this later */
|
||||||
conn->protocol &= ~PROT_MISSING; /* switch that one off again */
|
conn->protocol &= ~PROT_MISSING; /* switch that one off again */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CURL_DISABLE_HTTP
|
|
||||||
/************************************************************
|
|
||||||
* RESUME on a HTTP page is a tricky business. First, let's just check that
|
|
||||||
* 'range' isn't used, then set the range parameter and leave the resume as
|
|
||||||
* it is to inform about this situation for later use. We will then
|
|
||||||
* "attempt" to resume, and if we're talking to a HTTP/1.1 (or later)
|
|
||||||
* server, we will get the document resumed. If we talk to a HTTP/1.0
|
|
||||||
* server, we just fail since we can't rewind the file writing from within
|
|
||||||
* this function.
|
|
||||||
***********************************************************/
|
|
||||||
if(data->reqdata.resume_from) {
|
|
||||||
if(!data->reqdata.use_range) {
|
|
||||||
/* if it already was in use, we just skip this */
|
|
||||||
data->reqdata.range = aprintf("%" FORMAT_OFF_T "-", data->reqdata.resume_from);
|
|
||||||
if(!data->reqdata.range)
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
data->reqdata.rangestringalloc = TRUE; /* mark as allocated */
|
|
||||||
data->reqdata.use_range = 1; /* switch on range usage */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Setup internals depending on protocol
|
* Setup internals depending on protocol
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
@ -3206,6 +3193,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
#else
|
#else
|
||||||
failf(data, LIBCURL_NAME
|
failf(data, LIBCURL_NAME
|
||||||
" was built with TELNET disabled!");
|
" was built with TELNET disabled!");
|
||||||
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "DICT")) {
|
else if (strequal(conn->protostr, "DICT")) {
|
||||||
@ -3219,6 +3207,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
#else
|
#else
|
||||||
failf(data, LIBCURL_NAME
|
failf(data, LIBCURL_NAME
|
||||||
" was built with DICT disabled!");
|
" was built with DICT disabled!");
|
||||||
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "LDAP")) {
|
else if (strequal(conn->protostr, "LDAP")) {
|
||||||
@ -3232,6 +3221,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
#else
|
#else
|
||||||
failf(data, LIBCURL_NAME
|
failf(data, LIBCURL_NAME
|
||||||
" was built with LDAP disabled!");
|
" was built with LDAP disabled!");
|
||||||
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "FILE")) {
|
else if (strequal(conn->protostr, "FILE")) {
|
||||||
@ -3240,25 +3230,10 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
|
|
||||||
conn->curl_do = Curl_file;
|
conn->curl_do = Curl_file;
|
||||||
conn->curl_done = Curl_file_done;
|
conn->curl_done = Curl_file_done;
|
||||||
|
|
||||||
/* anyway, this is supposed to be the connect function so we better
|
|
||||||
at least check that the file is present here! */
|
|
||||||
result = Curl_file_connect(conn);
|
|
||||||
|
|
||||||
/* Setup a "faked" transfer that'll do nothing */
|
|
||||||
if(CURLE_OK == result) {
|
|
||||||
conn->data = data;
|
|
||||||
conn->bits.tcpconnect = TRUE; /* we are "connected */
|
|
||||||
ConnectionStore(data, conn);
|
|
||||||
|
|
||||||
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
|
|
||||||
-1, NULL); /* no upload */
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
#else
|
#else
|
||||||
failf(data, LIBCURL_NAME
|
failf(data, LIBCURL_NAME
|
||||||
" was built with FILE disabled!");
|
" was built with FILE disabled!");
|
||||||
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "TFTP")) {
|
else if (strequal(conn->protostr, "TFTP")) {
|
||||||
@ -3297,6 +3272,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
#else
|
#else
|
||||||
failf(data, LIBCURL_NAME
|
failf(data, LIBCURL_NAME
|
||||||
" was built with TFTP disabled!");
|
" was built with TFTP disabled!");
|
||||||
|
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (strequal(conn->protostr, "SCP")) {
|
else if (strequal(conn->protostr, "SCP")) {
|
||||||
@ -3344,21 +3320,11 @@ else {
|
|||||||
char *prox_portno;
|
char *prox_portno;
|
||||||
char *endofprot;
|
char *endofprot;
|
||||||
|
|
||||||
/* We need to make a duplicate of the proxy so that we can modify the
|
|
||||||
string safely. If 'proxy_alloc' is TRUE, the string is already
|
|
||||||
allocated and we can treat it as duplicated. */
|
|
||||||
char *proxydup=proxy_alloc?proxy:strdup(proxy);
|
|
||||||
|
|
||||||
/* We use 'proxyptr' to point to the proxy name from now on... */
|
/* We use 'proxyptr' to point to the proxy name from now on... */
|
||||||
char *proxyptr=proxydup;
|
char *proxyptr=proxy;
|
||||||
char *portptr;
|
char *portptr;
|
||||||
char *atsign;
|
char *atsign;
|
||||||
|
|
||||||
if(NULL == proxydup) {
|
|
||||||
failf(data, "memory shortage");
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We do the proxy host string parsing here. We want the host name and the
|
/* We do the proxy host string parsing here. We want the host name and the
|
||||||
* port name. Accept a protocol:// prefix, even though it should just be
|
* port name. Accept a protocol:// prefix, even though it should just be
|
||||||
* ignored.
|
* ignored.
|
||||||
@ -3404,15 +3370,15 @@ else {
|
|||||||
atsign = strdup(atsign+1); /* the right side of the @-letter */
|
atsign = strdup(atsign+1); /* the right side of the @-letter */
|
||||||
|
|
||||||
if(atsign) {
|
if(atsign) {
|
||||||
free(proxydup); /* free the former proxy string */
|
free(proxy); /* free the former proxy string */
|
||||||
proxydup = proxyptr = atsign; /* now use this instead */
|
proxy = proxyptr = atsign; /* now use this instead */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
res = CURLE_OUT_OF_MEMORY;
|
res = CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(res) {
|
if(res) {
|
||||||
free(proxydup); /* free the allocated proxy string */
|
free(proxy); /* free the allocated proxy string */
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3455,12 +3421,33 @@ else {
|
|||||||
conn->proxy.rawalloc = strdup(proxyptr);
|
conn->proxy.rawalloc = strdup(proxyptr);
|
||||||
conn->proxy.name = conn->proxy.rawalloc;
|
conn->proxy.name = conn->proxy.rawalloc;
|
||||||
|
|
||||||
free(proxydup); /* free the duplicate pointer and not the modified */
|
free(proxy);
|
||||||
proxy = NULL; /* this may have just been freed */
|
proxy = NULL;
|
||||||
if(!conn->proxy.rawalloc)
|
if(!conn->proxy.rawalloc)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* file: is a special case in that it doesn't need a network connection
|
||||||
|
***********************************************************************/
|
||||||
|
if (strequal(conn->protostr, "FILE")) {
|
||||||
|
/* anyway, this is supposed to be the connect function so we better
|
||||||
|
at least check that the file is present here! */
|
||||||
|
result = Curl_file_connect(conn);
|
||||||
|
|
||||||
|
/* Setup a "faked" transfer that'll do nothing */
|
||||||
|
if(CURLE_OK == result) {
|
||||||
|
conn->data = data;
|
||||||
|
conn->bits.tcpconnect = TRUE; /* we are "connected */
|
||||||
|
ConnectionStore(data, conn);
|
||||||
|
|
||||||
|
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
|
||||||
|
-1, NULL); /* no upload */
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* If the protocol is using SSL and HTTP proxy is used, we set
|
* If the protocol is using SSL and HTTP proxy is used, we set
|
||||||
* the tunnel_proxy bit.
|
* the tunnel_proxy bit.
|
||||||
@ -3678,6 +3665,28 @@ else {
|
|||||||
if(!conn->user || !conn->passwd)
|
if(!conn->user || !conn->passwd)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
#ifndef CURL_DISABLE_HTTP
|
||||||
|
/************************************************************
|
||||||
|
* RESUME on a HTTP page is a tricky business. First, let's just check that
|
||||||
|
* 'range' isn't used, then set the range parameter and leave the resume as
|
||||||
|
* it is to inform about this situation for later use. We will then
|
||||||
|
* "attempt" to resume, and if we're talking to a HTTP/1.1 (or later)
|
||||||
|
* server, we will get the document resumed. If we talk to a HTTP/1.0
|
||||||
|
* server, we just fail since we can't rewind the file writing from within
|
||||||
|
* this function.
|
||||||
|
***********************************************************/
|
||||||
|
if(data->reqdata.resume_from) {
|
||||||
|
if(!data->reqdata.use_range) {
|
||||||
|
/* if it already was in use, we just skip this */
|
||||||
|
data->reqdata.range = aprintf("%" FORMAT_OFF_T "-", data->reqdata.resume_from);
|
||||||
|
if(!data->reqdata.range)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
data->reqdata.rangestringalloc = TRUE; /* mark as allocated */
|
||||||
|
data->reqdata.use_range = 1; /* switch on range usage */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Check the current list of connections to see if we can
|
* Check the current list of connections to see if we can
|
||||||
* re-use an already existing one or if we have to create a
|
* re-use an already existing one or if we have to create a
|
||||||
@ -3797,7 +3806,7 @@ else {
|
|||||||
|
|
||||||
infof(data, "Re-using existing connection! (#%ld) with host %s\n",
|
infof(data, "Re-using existing connection! (#%ld) with host %s\n",
|
||||||
conn->connectindex,
|
conn->connectindex,
|
||||||
proxy?conn->proxy.dispname:conn->host.dispname);
|
conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
|
@ -37,4 +37,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
|
|||||||
test274 test275 test524 test525 test276 test277 test526 test527 test528 \
|
test274 test275 test524 test525 test276 test277 test526 test527 test528 \
|
||||||
test530 DISABLED test278 test279 test531 test280 test529 test532 test533 \
|
test530 DISABLED test278 test279 test531 test280 test529 test532 test533 \
|
||||||
test534 test535 test281 test537 test282 test283 test284 test538 test285 \
|
test534 test535 test281 test537 test282 test283 test284 test538 test285 \
|
||||||
test286 test307 test308 test287 test400
|
test286 test307 test308 test287 test400 test288
|
||||||
|
42
tests/data/test288
Normal file
42
tests/data/test288
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<testcase>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
foo
|
||||||
|
bar
|
||||||
|
bar
|
||||||
|
foo
|
||||||
|
moo
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
none
|
||||||
|
</server>
|
||||||
|
<features>
|
||||||
|
file
|
||||||
|
</features>
|
||||||
|
<name>
|
||||||
|
file:// with (unsupported) proxy, authentication and range
|
||||||
|
</name>
|
||||||
|
<setenv>
|
||||||
|
all_proxy=http://fake:user@%HOSTIP:%HTTPPORT/
|
||||||
|
</setenv>
|
||||||
|
<command>
|
||||||
|
file://localhost/%PWD/log/test288.txt
|
||||||
|
</command>
|
||||||
|
<file name="log/test288.txt">
|
||||||
|
foo
|
||||||
|
bar
|
||||||
|
bar
|
||||||
|
foo
|
||||||
|
moo
|
||||||
|
</file>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
Loading…
Reference in New Issue
Block a user