From dcf7310b2d6b40ac37358f4d69f6e3e9aa3c9c70 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 27 May 2004 07:48:09 +0000 Subject: fixed curl_easy_duphandle() to properly clean up all memory if any memory function fails and it returns NULL --- lib/easy.c | 141 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 84 insertions(+), 57 deletions(-) (limited to 'lib') 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; -- cgit v1.2.3