diff options
| -rw-r--r-- | CHANGES | 4 | ||||
| -rw-r--r-- | RELEASE-NOTES | 1 | ||||
| -rw-r--r-- | src/main.c | 169 | 
3 files changed, 100 insertions, 74 deletions
@@ -6,6 +6,10 @@                                    Changelog +Yang Tse (16 Jan 2008) +- Improved handling of out of memory in the command line tool that afected +  data url encoded HTTP POSTs when reading it from a file. +  Daniel S (16 Jan 2008)  - Dmitry Kurochkin worked a lot on improving the HTTP Pipelining support that    previously had a number of flaws, perhaps most notably when an application diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 81c65c140..ba5ec5282 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -55,6 +55,7 @@ This release includes the following bugfixes:   o libcurl hang with huge POST request and request-body read from callback   o removed extra newlines from many error messages   o improved pipelining + o improved OOM handling for data url encoded HTTP POSTs when read from a file  This release includes the following known bugs: diff --git a/src/main.c b/src/main.c index 1b0036bcd..b7e06e436 100644 --- a/src/main.c +++ b/src/main.c @@ -803,71 +803,6 @@ static void GetStr(char **string,      *string = NULL;  } -static char *file2string(FILE *file) -{ -  char buffer[256]; -  char *ptr; -  char *string=NULL; -  size_t len=0; -  size_t stringlen; - -  if(file) { -    while(fgets(buffer, sizeof(buffer), file)) { -      ptr= strchr(buffer, '\r'); -      if(ptr) -        *ptr=0; -      ptr= strchr(buffer, '\n'); -      if(ptr) -        *ptr=0; -      stringlen=strlen(buffer); -      if(string) -        string = realloc(string, len+stringlen+1); -      else -        string = malloc(stringlen+1); - -      strcpy(string+len, buffer); - -      len+=stringlen; -    } -    return string; -  } -  else -    return NULL; /* no string */ -} - -static char *file2memory(FILE *file, long *size) -{ -  char buffer[1024]; -  char *string=NULL; -  char *newstring=NULL; -  size_t len=0; -  long stringlen=0; - -  if(file) { -    while((len = fread(buffer, 1, sizeof(buffer), file))) { -      if(string) { -        newstring = realloc(string, len+stringlen+1); -        if(newstring) -          string = newstring; -        else -          break; /* no more strings attached! :-) */ -      } -      else -        string = malloc(len+1); -      memcpy(&string[stringlen], buffer, len); -      stringlen+=len; -    } -    if (string) { -      /* NUL terminate the buffer in case it's treated as a string later */ -      string[stringlen] = 0; -    } -    *size = stringlen; -    return string; -  } -  else -    return NULL; /* no string */ -} -  static void clean_getout(struct Configurable *config)  {    struct getout *node=config->url_list; @@ -1310,6 +1245,82 @@ static const char *param2text(int res)    }  } +static ParameterError file2string(char **bufp, FILE *file) +{ +  char buffer[256]; +  char *ptr; +  char *string = NULL; +  size_t stringlen = 0; +  size_t buflen; + +  if(file) { +    while(fgets(buffer, sizeof(buffer), file)) { +      if((ptr = strchr(buffer, '\r')) != NULL) +        *ptr = '\0'; +      if((ptr = strchr(buffer, '\n')) != NULL) +        *ptr = '\0'; +      buflen = strlen(buffer); +      if((ptr = realloc(string, stringlen+buflen+1)) == NULL) { +        if(string) +          free(string); +        return PARAM_NO_MEM; +      } +      string = ptr; +      strcpy(string+stringlen, buffer); +      stringlen += buflen; +    } +  } +  *bufp = string; +  return PARAM_OK; +} + +static ParameterError file2memory(char **bufp, size_t *size, FILE *file) +{ +  char *newbuf; +  char *buffer = NULL; +  size_t alloc = 512; +  size_t nused = 0; +  size_t nread; + +  if(file) { +    do { +      if(!buffer || (alloc == nused)) { +        /* size_t overflow detection for huge files */ +        if(alloc+1 > ((size_t)-1)/2) { +          if(buffer) +            free(buffer); +          return PARAM_NO_MEM; +        } +        alloc *= 2; +        /* allocate an extra char, reserved space, for null termination */ +        if((newbuf = realloc(buffer, alloc+1)) == NULL) { +          if(buffer) +            free(buffer); +          return PARAM_NO_MEM; +        } +        buffer = newbuf; +      } +      nread = fread(buffer+nused, 1, alloc-nused, file); +      nused += nread; +    } while(nread); +    /* null terminate the buffer in case it's used as a string later */ +    buffer[nused] = '\0'; +    /* free trailing slack space, if possible */ +    if(alloc != nused) { +      if((newbuf = realloc(buffer, nused+1)) != NULL) +        buffer = newbuf; +    } +    /* discard buffer if nothing was read */ +    if(!nused) { +      free(buffer); +      buffer = NULL; /* no string */ +    } +  } +  *size = nused; +  *bufp = buffer; +  return PARAM_OK; +} +  static void cleanarg(char *str)  {  #ifdef HAVE_WRITABLE_ARGV @@ -2158,7 +2169,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */             * the content.             */            char *p = strchr(nextarg, '='); -          long size = 0; +          size_t size = 0;            size_t nlen;            char is_file;            if(!p) @@ -2188,14 +2199,16 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */                        "an empty POST.\n", nextarg);              } -            postdata = file2memory(file, &size); +            err = file2memory(&postdata, &size, file);              if(file && (file != stdin))                fclose(file); +            if(err) +              return err;            }            else {              GetStr(&postdata, p); -            size = (long)strlen(postdata); +            size = strlen(postdata);            }            if(!postdata) { @@ -2229,6 +2242,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */            }          }          else if('@' == *nextarg) { +          size_t size = 0;            /* the data begins with a '@' letter, it means that a file name               or - (stdin) follows */            nextarg++; /* pass the @ */ @@ -2245,13 +2259,18 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */                      "an empty POST.\n", nextarg);            } -          if(subletter == 'b') /* forced binary */ -            postdata = file2memory(file, &config->postfieldsize); +          if(subletter == 'b') { +            /* forced binary */ +            err = file2memory(&postdata, &size, file); +            config->postfieldsize = size; +          }            else -            postdata = file2string(file); +            err = file2string(&postdata, file);            if(file && (file != stdin))              fclose(file); +          if(err) +            return err;            if(!postdata) {              /* no data from the file, point to a zero byte string to make this @@ -2714,11 +2733,13 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */            file = stdin;          else            file = fopen(nextarg, "r"); -        config->writeout = file2string(file); -        if(!config->writeout) -          warnf(config, "Failed to read %s", file); +        err = file2string(&config->writeout, file);          if(file && (file != stdin))            fclose(file); +        if(err) +          return err; +        if(!config->writeout) +          warnf(config, "Failed to read %s", file);        }        else          GetStr(&config->writeout, nextarg);  | 
