summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2004-05-27 07:48:09 +0000
committerDaniel Stenberg <daniel@haxx.se>2004-05-27 07:48:09 +0000
commitdcf7310b2d6b40ac37358f4d69f6e3e9aa3c9c70 (patch)
treea4d6dc21717a7ae73e6276643a443e40fe09b7a9
parentc2e8ba0fbaaf6e9dc73df9c3ede3dcf5986ef9c2 (diff)
downloadgnurl-dcf7310b2d6b40ac37358f4d69f6e3e9aa3c9c70.tar.gz
gnurl-dcf7310b2d6b40ac37358f4d69f6e3e9aa3c9c70.tar.bz2
gnurl-dcf7310b2d6b40ac37358f4d69f6e3e9aa3c9c70.zip
fixed curl_easy_duphandle() to properly clean up all memory if any memory
function fails and it returns NULL
-rw-r--r--lib/easy.c141
1 files changed, 84 insertions, 57 deletions
diff --git a/lib/easy.c b/lib/easy.c
index 85a8abf12..5c3062712 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -420,74 +420,101 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
*/
CURL *curl_easy_duphandle(CURL *incurl)
{
+ bool fail = TRUE;
struct SessionHandle *data=(struct SessionHandle *)incurl;
struct SessionHandle *outcurl = (struct SessionHandle *)
- malloc(sizeof(struct SessionHandle));
+ calloc(sizeof(struct SessionHandle), 1);
if(NULL == outcurl)
return NULL; /* failure */
- /* start with clearing the entire new struct */
- memset(outcurl, 0, sizeof(struct SessionHandle));
+ do {
-#ifdef USE_ARES
- /* If we use ares, we need to setup a new ares channel for the new handle */
- if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel)) {
- free(outcurl);
- return NULL;
- }
-#endif
-
- /*
- * We setup a few buffers we need. We should probably make them
- * get setup on-demand in the code, as that would probably decrease
- * the likeliness of us forgetting to init a buffer here in the future.
- */
- outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
- if(!outcurl->state.headerbuff) {
- free(outcurl); /* free the memory again */
- return NULL;
- }
- outcurl->state.headersize=HEADERSIZE;
+ /*
+ * We setup a few buffers we need. We should probably make them
+ * get setup on-demand in the code, as that would probably decrease
+ * the likeliness of us forgetting to init a buffer here in the future.
+ */
+ outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
+ if(!outcurl->state.headerbuff) {
+ break;
+ }
+ outcurl->state.headersize=HEADERSIZE;
- /* copy all userdefined values */
- outcurl->set = data->set;
- outcurl->state.numconnects = data->state.numconnects;
- outcurl->state.connects = (struct connectdata **)
+ /* copy all userdefined values */
+ outcurl->set = data->set;
+ outcurl->state.numconnects = data->state.numconnects;
+ outcurl->state.connects = (struct connectdata **)
malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
- if(!outcurl->state.connects) {
- free(outcurl->state.headerbuff);
- free(outcurl);
- return NULL;
- }
- memset(outcurl->state.connects, 0,
- sizeof(struct connectdata *)*outcurl->state.numconnects);
-
- outcurl->progress.flags = data->progress.flags;
- outcurl->progress.callback = data->progress.callback;
-
- if(data->cookies)
- /* If cookies are enabled in the parent handle, we enable them
- in the clone as well! */
- outcurl->cookies = Curl_cookie_init(data,
- data->cookies->filename,
- outcurl->cookies,
- data->set.cookiesession);
-
- /* duplicate all values in 'change' */
- if(data->change.url) {
- outcurl->change.url = strdup(data->change.url);
- outcurl->change.url_alloc = TRUE;
- }
- if(data->change.proxy) {
- outcurl->change.proxy = strdup(data->change.proxy);
- outcurl->change.proxy_alloc = TRUE;
- }
- if(data->change.referer) {
- outcurl->change.referer = strdup(data->change.referer);
- outcurl->change.referer_alloc = TRUE;
+ if(!outcurl->state.connects) {
+ break;
+ }
+
+ memset(outcurl->state.connects, 0,
+ sizeof(struct connectdata *)*outcurl->state.numconnects);
+
+ outcurl->progress.flags = data->progress.flags;
+ outcurl->progress.callback = data->progress.callback;
+
+ if(data->cookies) {
+ /* If cookies are enabled in the parent handle, we enable them
+ in the clone as well! */
+ outcurl->cookies = Curl_cookie_init(data,
+ data->cookies->filename,
+ outcurl->cookies,
+ data->set.cookiesession);
+ if(!outcurl->cookies) {
+ break;
+ }
+ }
+
+ /* duplicate all values in 'change' */
+ if(data->change.url) {
+ outcurl->change.url = strdup(data->change.url);
+ if(!outcurl->change.url)
+ break;
+ outcurl->change.url_alloc = TRUE;
+ }
+ if(data->change.proxy) {
+ outcurl->change.proxy = strdup(data->change.proxy);
+ if(!outcurl->change.proxy)
+ break;
+ outcurl->change.proxy_alloc = TRUE;
+ }
+ if(data->change.referer) {
+ outcurl->change.referer = strdup(data->change.referer);
+ if(!outcurl->change.referer)
+ break;
+ outcurl->change.referer_alloc = TRUE;
+ }
+
+#ifdef USE_ARES
+ /* If we use ares, we setup a new ares channel for the new handle */
+ if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
+ break;
+#endif
+
+ fail = FALSE; /* we reach this point and thus we are OK */
+
+ } while(0);
+
+ if(fail) {
+ if(outcurl) {
+ if(outcurl->state.connects)
+ free(outcurl->state.connects);
+ if(outcurl->state.headerbuff)
+ free(outcurl->state.headerbuff);
+ if(outcurl->change.proxy)
+ free(outcurl->change.proxy);
+ if(outcurl->change.url)
+ free(outcurl->change.url);
+ if(outcurl->change.referer)
+ free(outcurl->change.referer);
+ free(outcurl); /* free the memory again */
+ outcurl = NULL;
+ }
}
return outcurl;