fix handling of out of memory in the command line tool that afected
data url encoded HTTP POSTs when reading it from a file.
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
Changelog
|
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)
|
Daniel S (16 Jan 2008)
|
||||||
- Dmitry Kurochkin worked a lot on improving the HTTP Pipelining support that
|
- Dmitry Kurochkin worked a lot on improving the HTTP Pipelining support that
|
||||||
previously had a number of flaws, perhaps most notably when an application
|
previously had a number of flaws, perhaps most notably when an application
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ This release includes the following bugfixes:
|
|||||||
o libcurl hang with huge POST request and request-body read from callback
|
o libcurl hang with huge POST request and request-body read from callback
|
||||||
o removed extra newlines from many error messages
|
o removed extra newlines from many error messages
|
||||||
o improved pipelining
|
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:
|
This release includes the following known bugs:
|
||||||
|
|
||||||
|
|||||||
169
src/main.c
169
src/main.c
@@ -803,71 +803,6 @@ static void GetStr(char **string,
|
|||||||
*string = NULL;
|
*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)
|
static void clean_getout(struct Configurable *config)
|
||||||
{
|
{
|
||||||
struct getout *node=config->url_list;
|
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)
|
static void cleanarg(char *str)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_WRITABLE_ARGV
|
#ifdef HAVE_WRITABLE_ARGV
|
||||||
@@ -2158,7 +2169,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
* the content.
|
* the content.
|
||||||
*/
|
*/
|
||||||
char *p = strchr(nextarg, '=');
|
char *p = strchr(nextarg, '=');
|
||||||
long size = 0;
|
size_t size = 0;
|
||||||
size_t nlen;
|
size_t nlen;
|
||||||
char is_file;
|
char is_file;
|
||||||
if(!p)
|
if(!p)
|
||||||
@@ -2188,14 +2199,16 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
"an empty POST.\n", nextarg);
|
"an empty POST.\n", nextarg);
|
||||||
}
|
}
|
||||||
|
|
||||||
postdata = file2memory(file, &size);
|
err = file2memory(&postdata, &size, file);
|
||||||
|
|
||||||
if(file && (file != stdin))
|
if(file && (file != stdin))
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
if(err)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GetStr(&postdata, p);
|
GetStr(&postdata, p);
|
||||||
size = (long)strlen(postdata);
|
size = strlen(postdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!postdata) {
|
if(!postdata) {
|
||||||
@@ -2229,6 +2242,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if('@' == *nextarg) {
|
else if('@' == *nextarg) {
|
||||||
|
size_t size = 0;
|
||||||
/* the data begins with a '@' letter, it means that a file name
|
/* the data begins with a '@' letter, it means that a file name
|
||||||
or - (stdin) follows */
|
or - (stdin) follows */
|
||||||
nextarg++; /* pass the @ */
|
nextarg++; /* pass the @ */
|
||||||
@@ -2245,13 +2259,18 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
"an empty POST.\n", nextarg);
|
"an empty POST.\n", nextarg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(subletter == 'b') /* forced binary */
|
if(subletter == 'b') {
|
||||||
postdata = file2memory(file, &config->postfieldsize);
|
/* forced binary */
|
||||||
|
err = file2memory(&postdata, &size, file);
|
||||||
|
config->postfieldsize = size;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
postdata = file2string(file);
|
err = file2string(&postdata, file);
|
||||||
|
|
||||||
if(file && (file != stdin))
|
if(file && (file != stdin))
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
if(err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if(!postdata) {
|
if(!postdata) {
|
||||||
/* no data from the file, point to a zero byte string to make this
|
/* 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;
|
file = stdin;
|
||||||
else
|
else
|
||||||
file = fopen(nextarg, "r");
|
file = fopen(nextarg, "r");
|
||||||
config->writeout = file2string(file);
|
err = file2string(&config->writeout, file);
|
||||||
if(!config->writeout)
|
|
||||||
warnf(config, "Failed to read %s", file);
|
|
||||||
if(file && (file != stdin))
|
if(file && (file != stdin))
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
if(err)
|
||||||
|
return err;
|
||||||
|
if(!config->writeout)
|
||||||
|
warnf(config, "Failed to read %s", file);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GetStr(&config->writeout, nextarg);
|
GetStr(&config->writeout, nextarg);
|
||||||
|
|||||||
Reference in New Issue
Block a user