diff options
author | Daniel Stenberg <daniel@haxx.se> | 2020-09-08 13:46:51 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2020-09-09 08:13:55 +0200 |
commit | 7d8a66193e6a8c63bee062e24d4db51a9968db7c (patch) | |
tree | 98b15150d0fe59bbf3f8ea7c619855a3117980b1 /src/tool_parsecfg.c | |
parent | 36f60494aea504b269e740af49135c967813e5b1 (diff) | |
download | curl-bagder/parsecfg-lessmalloc.tar.gz |
curl: load config files using fewer mallocsbagder/parsecfg-lessmalloc
... and use a maximum line length (100K). As a result, also then
avoids the possible integer overflow in the old code.
Reported-by: ihsinme on github
Assisted-by: Jay Satiro
Closes #5941
Diffstat (limited to 'src/tool_parsecfg.c')
-rw-r--r-- | src/tool_parsecfg.c | 65 |
1 files changed, 20 insertions, 45 deletions
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c index 4e56492cb..92b78006c 100644 --- a/src/tool_parsecfg.c +++ b/src/tool_parsecfg.c @@ -39,7 +39,18 @@ #define ISSEP(x,dash) (!dash && (((x) == '=') || ((x) == ':'))) static const char *unslashquote(const char *line, char *param); -static char *my_get_line(FILE *fp); + +#define MAX_CONFIG_LINE_LENGTH (100*1024) +/* + * Reads a line from the given file, ensure the buffer is NUL terminated. + * Returns TRUE on error. + */ +static bool my_get_line(FILE *fp, char *buf, int buflen) +{ + if(!fgets(buf, buflen, fp)) + return FALSE; /* error */ + return TRUE; +} #ifdef WIN32 static FILE *execpath(const char *filename) @@ -135,13 +146,18 @@ int parseconfig(const char *filename, struct GlobalConfig *global) if(file) { char *line; - char *aline; char *option; char *param; int lineno = 0; bool dashed_option; + char *aline = malloc(MAX_CONFIG_LINE_LENGTH); + if(!aline) { + if(file != stdin) + fclose(file); + return 1; + } - while(NULL != (aline = my_get_line(file))) { + while(my_get_line(file, aline, MAX_CONFIG_LINE_LENGTH)) { int res; bool alloced_param = FALSE; lineno++; @@ -158,7 +174,6 @@ int parseconfig(const char *filename, struct GlobalConfig *global) case '\n': case '*': case '\0': - Curl_safefree(aline); continue; } @@ -190,7 +205,6 @@ int parseconfig(const char *filename, struct GlobalConfig *global) param = malloc(strlen(line) + 1); /* parameter */ if(!param) { /* out of memory */ - Curl_safefree(aline); rc = 1; break; } @@ -279,9 +293,8 @@ int parseconfig(const char *filename, struct GlobalConfig *global) if(alloced_param) Curl_safefree(param); - - Curl_safefree(aline); } + free(aline); if(file != stdin) fclose(file); } @@ -333,41 +346,3 @@ static const char *unslashquote(const char *line, char *param) return line; } -/* - * Reads a line from the given file, ensuring is NUL terminated. - * The pointer must be freed by the caller. - * NULL is returned on an out of memory condition. - */ -static char *my_get_line(FILE *fp) -{ - char buf[4096]; - char *nl = NULL; - char *line = NULL; - - do { - if(NULL == fgets(buf, sizeof(buf), fp)) - break; - if(!line) { - line = strdup(buf); - if(!line) - return NULL; - } - else { - char *ptr; - size_t linelen = strlen(line); - ptr = realloc(line, linelen + strlen(buf) + 1); - if(!ptr) { - Curl_safefree(line); - return NULL; - } - line = ptr; - strcpy(&line[linelen], buf); - } - nl = strchr(line, '\n'); - } while(!nl); - - if(nl) - *nl = '\0'; - - return line; -} |