From 5bf0d74120a92fb834b0d13098c0b5e93249a84f Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 5 Oct 2011 15:06:26 +0200 Subject: curl tool: OOM handling fixes --- src/tool_getparam.c | 36 +++++++++++++++++++++++++++--------- src/tool_operate.c | 9 ++++++++- src/tool_operhlp.c | 19 +++++++++++++------ src/tool_operhlp.h | 2 +- src/tool_paramhlp.c | 38 +++++++++++++++++++++----------------- src/tool_paramhlp.h | 4 +--- 6 files changed, 71 insertions(+), 37 deletions(-) diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 7ddd7367a..ae2970fb7 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -600,7 +600,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ if(config->url_get || ((config->url_get = config->url_list) != NULL)) { /* there's a node here, if it already is filled-in continue to find an "empty" node */ - while(config->url_get && (config->url_get->flags&GETOUT_URL)) + while(config->url_get && (config->url_get->flags & GETOUT_URL)) config->url_get = config->url_get->next; } @@ -613,7 +613,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ /* there was no free node, create one! */ url = new_getout(config); - if(url) { + if(!url) + return PARAM_NO_MEM; + else { /* fill in the URL */ GetStr(&url->url, nextarg); url->flags |= GETOUT_URL; @@ -941,6 +943,8 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ /* no data from the file, point to a zero byte string to make this get sent as a POST anyway */ postdata = strdup(""); + if(!postdata) + return PARAM_NO_MEM; size = 0; } else { @@ -1004,7 +1008,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ if(!postdata) { /* no data from the file, point to a zero byte string to make this get sent as a POST anyway */ - postdata=strdup(""); + postdata = strdup(""); + if(!postdata) + return PARAM_NO_MEM; } } else { @@ -1298,7 +1304,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ if(config->url_out || ((config->url_out = config->url_list) != NULL)) { /* there's a node here, if it already is filled-in continue to find an "empty" node */ - while(config->url_out && (config->url_out->flags&GETOUT_OUTFILE)) + while(config->url_out && (config->url_out->flags & GETOUT_OUTFILE)) config->url_out = config->url_out->next; } @@ -1311,7 +1317,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ /* there was no free node, create one! */ url = new_getout(config); - if(url) { + if(!url) + return PARAM_NO_MEM; + else { /* fill in the outfile */ if('o' == letter) { GetStr(&url->outfile, nextarg); @@ -1379,6 +1387,8 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ snprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off); Curl_safefree(config->range); config->range = strdup(buffer); + if(!config->range) + return PARAM_NO_MEM; } { /* byte range requested */ @@ -1427,7 +1437,7 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ if(config->url_out || ((config->url_out = config->url_list) != NULL)) { /* there's a node here, if it already is filled-in continue to find an "empty" node */ - while(config->url_out && (config->url_out->flags&GETOUT_UPLOAD)) + while(config->url_out && (config->url_out->flags & GETOUT_UPLOAD)) config->url_out = config->url_out->next; } @@ -1440,7 +1450,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ /* there was no free node, create one! */ url = new_getout(config); - if(url) { + if(!url) + return PARAM_NO_MEM; + else { url->flags |= GETOUT_UPLOAD; /* mark -T used */ if(!*nextarg) url->flags |= GETOUT_NOUPLOAD; @@ -1455,19 +1467,25 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ /* user:password */ GetStr(&config->userpwd, nextarg); cleanarg(nextarg); - checkpasswd("host", &config->userpwd); + err = checkpasswd("host", &config->userpwd); + if(err) + return err; break; case 'U': /* Proxy user:password */ GetStr(&config->proxyuserpwd, nextarg); cleanarg(nextarg); - checkpasswd("proxy", &config->proxyuserpwd); + err = checkpasswd("proxy", &config->proxyuserpwd); + if(err) + return err; break; case 'v': if(toggle) { /* the '%' thing here will cause the trace get sent to stderr */ Curl_safefree(config->trace_dump); config->trace_dump = strdup("%"); + if(!config->trace_dump) + return PARAM_NO_MEM; if(config->tracetype && (config->tracetype != TRACE_PLAIN)) warnf(config, "-v, --verbose overrides an earlier trace/verbose option\n"); diff --git a/src/tool_operate.c b/src/tool_operate.c index 9624f424a..d4671eb39 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -317,6 +317,11 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) /* Use the postfields data for a http get */ httpgetfields = strdup(config->postfields); Curl_safefree(config->postfields); + if(!httpgetfields) { + helpf(config->errors, "out of memory\n"); + res = CURLE_OUT_OF_MEMORY; + goto quit_curl; + } if(SetHTTPrequest(config, (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET), &config->httpreq)) { @@ -515,7 +520,9 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) if(!outfile) { /* extract the file name from the URL */ - outfile = get_url_file_name(this_url); + res = get_url_file_name(&outfile, this_url); + if(res) + goto show_error; if((!outfile || !*outfile) && !config->content_disposition) { helpf(config->errors, "Remote file name has no length!\n"); res = CURLE_WRITE_ERROR; diff --git a/src/tool_operhlp.c b/src/tool_operhlp.c index 1a72035f7..5a6a670f9 100644 --- a/src/tool_operhlp.c +++ b/src/tool_operhlp.c @@ -152,14 +152,17 @@ char *add_file_name_to_url(CURL *curl, char *url, const char *filename) } /* Extracts the name portion of the URL. - * Returns a heap-allocated string, or NULL if no name part + * Returns a pointer to a heap-allocated string or NULL if + * no name part, at location indicated by first argument. */ -char *get_url_file_name(const char *url) +CURLcode get_url_file_name(char **filename, const char *url) { - char *fn = NULL; + const char *pc; + + *filename = NULL; /* Find and get the remote file name */ - const char *pc = strstr(url, "://"); + pc = strstr(url, "://"); if(pc) pc += 3; else @@ -169,9 +172,13 @@ char *get_url_file_name(const char *url) if(pc) { /* duplicate the string beyond the slash */ pc++; - fn = *pc ? strdup(pc): NULL; + if(*pc) { + *filename = strdup(pc); + if(!*filename) + return CURLE_OUT_OF_MEMORY; + } } - return fn; + return CURLE_OK; } /* diff --git a/src/tool_operhlp.h b/src/tool_operhlp.h index 911f2f8e0..3629bf13a 100644 --- a/src/tool_operhlp.h +++ b/src/tool_operhlp.h @@ -35,7 +35,7 @@ bool stdin_upload(const char *uploadfile); char *add_file_name_to_url(CURL *curl, char *url, const char *filename); -char *get_url_file_name(const char *url); +CURLcode get_url_file_name(char **filename, const char *url); CURLcode main_init(void); diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c index 4f36719be..97681c1bd 100644 --- a/src/tool_paramhlp.c +++ b/src/tool_paramhlp.c @@ -41,12 +41,9 @@ struct getout *new_getout(struct Configurable *config) { - struct getout *node =malloc(sizeof(struct getout)); - struct getout *last= config->url_last; + struct getout *node = calloc(1, sizeof(struct getout)); + struct getout *last = config->url_last; if(node) { - /* clear the struct */ - memset(node, 0, sizeof(struct getout)); - /* append this new node last in the list */ if(last) last->next = node; @@ -120,8 +117,11 @@ ParameterError file2memory(char **bufp, size_t *size, FILE *file) buffer[nused] = '\0'; /* free trailing slack space, if possible */ if(alloc != nused) { - if((newbuf = realloc(buffer, nused+1)) != NULL) - buffer = newbuf; + if((newbuf = realloc(buffer, nused+1)) == NULL) { + Curl_safefree(buffer); + return PARAM_NO_MEM; + } + buffer = newbuf; } /* discard buffer if nothing was read */ if(!nused) { @@ -221,6 +221,8 @@ long proto2num(struct Configurable *config, long *val, const char *str) return 1; buffer = strdup(str); /* because strtok corrupts it */ + if(!buffer) + return 1; for(token = strtok(buffer, sep); token; @@ -298,17 +300,18 @@ int str2offset(curl_off_t *val, const char *str) return 0; } -void checkpasswd(const char *kind, /* for what purpose */ - char **userpwd) /* pointer to allocated string */ +ParameterError checkpasswd(const char *kind, /* for what purpose */ + char **userpwd) /* pointer to allocated string */ { char *ptr; + if(!*userpwd) - return; + return PARAM_OK; ptr = strchr(*userpwd, ':'); if(!ptr) { /* no password present, prompt for one */ - char passwd[256]=""; + char passwd[256] = ""; char prompt[256]; size_t passwdlen; size_t userlen = strlen(*userpwd); @@ -327,14 +330,15 @@ void checkpasswd(const char *kind, /* for what purpose */ passptr = realloc(*userpwd, passwdlen + 1 + /* an extra for the colon */ userlen + 1); /* an extra for the zero */ + if(!passptr) + return PARAM_NO_MEM; - if(passptr) { - /* append the password separated with a colon */ - passptr[userlen]=':'; - memcpy(&passptr[userlen+1], passwd, passwdlen+1); - *userpwd = passptr; - } + /* append the password separated with a colon */ + passptr[userlen] = ':'; + memcpy(&passptr[userlen+1], passwd, passwdlen+1); + *userpwd = passptr; } + return PARAM_OK; } ParameterError add2list(struct curl_slist **list, const char *ptr) diff --git a/src/tool_paramhlp.h b/src/tool_paramhlp.h index 8b7ec9481..f17999198 100644 --- a/src/tool_paramhlp.h +++ b/src/tool_paramhlp.h @@ -37,7 +37,7 @@ long proto2num(struct Configurable *config, long *val, const char *str); int str2offset(curl_off_t *val, const char *str); -void checkpasswd(const char *kind, char **userpwd); +ParameterError checkpasswd(const char *kind, char **userpwd); ParameterError add2list(struct curl_slist **list, const char *ptr); @@ -47,7 +47,5 @@ int ftpcccmethod(struct Configurable *config, const char *str); long delegation(struct Configurable *config, char *str); - - #endif /* HEADER_CURL_TOOL_PARAMHLP_H */ -- cgit v1.2.3