diff options
| author | Daniel Stenberg <daniel@haxx.se> | 2004-05-27 07:48:09 +0000 | 
|---|---|---|
| committer | Daniel Stenberg <daniel@haxx.se> | 2004-05-27 07:48:09 +0000 | 
| commit | dcf7310b2d6b40ac37358f4d69f6e3e9aa3c9c70 (patch) | |
| tree | a4d6dc21717a7ae73e6276643a443e40fe09b7a9 | |
| parent | c2e8ba0fbaaf6e9dc73df9c3ede3dcf5986ef9c2 (diff) | |
fixed curl_easy_duphandle() to properly clean up all memory if any memory
function fails and it returns NULL
| -rw-r--r-- | lib/easy.c | 141 | 
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; | 
