config_file: Guard against calloc/malloc/realloc failure cases

This commit is contained in:
Lioncash 2014-09-14 18:20:13 -04:00
parent 05024d529a
commit d4f01cafdf

View File

@ -63,22 +63,36 @@ struct config_file
struct include_list *includes; struct include_list *includes;
}; };
static config_file_t *config_file_new_internal(const char *path, static config_file_t *config_file_new_internal(const char *path, unsigned depth);
unsigned depth); void config_file_free(config_file_t *conf);
static char *getaline(FILE *file) static char *getaline(FILE *file)
{ {
char *newline = (char*)malloc(9); char* newline = (char*)malloc(9);
char* newline_tmp = NULL;
size_t cur_size = 8; size_t cur_size = 8;
size_t index = 0; size_t index = 0;
int in = getc(file); int in = getc(file);
if (!newline)
return NULL;
while (in != EOF && in != '\n') while (in != EOF && in != '\n')
{ {
if (index == cur_size) if (index == cur_size)
{ {
cur_size *= 2; cur_size *= 2;
newline = (char*)realloc(newline, cur_size + 1); newline = (char*)realloc(newline, cur_size + 1);
if (newline_tmp)
{
newline = newline_tmp;
}
else
{
free(newline);
return NULL;
}
} }
newline[index++] = in; newline[index++] = in;
@ -173,6 +187,10 @@ static void add_include_list(config_file_t *conf, const char *path)
{ {
struct include_list *head = conf->includes; struct include_list *head = conf->includes;
struct include_list *node = (struct include_list*)calloc(1, sizeof(*node)); struct include_list *node = (struct include_list*)calloc(1, sizeof(*node));
if (!node)
return;
node->path = strdup(path); node->path = strdup(path);
if (head) if (head)
@ -267,10 +285,19 @@ static char *strip_comment(char *str)
static bool parse_line(config_file_t *conf, static bool parse_line(config_file_t *conf,
struct config_entry_list *list, char *line) struct config_entry_list *list, char *line)
{ {
if (!*line) char* comment = NULL;
char* key = (char*)malloc(9);
char* key_tmp = NULL;
size_t cur_size = 8;
size_t index = 0;
if (!line || !*line)
return false; return false;
char *comment = strip_comment(line); if (!key)
return false;
comment = strip_comment(line);
/* Starting line with # and include includes config files. */ /* Starting line with # and include includes config files. */
if ((comment == line) && (conf->include_depth < MAX_INCLUDE_DEPTH)) if ((comment == line) && (conf->include_depth < MAX_INCLUDE_DEPTH))
@ -283,22 +310,30 @@ static bool parse_line(config_file_t *conf,
} }
} }
else if (conf->include_depth >= MAX_INCLUDE_DEPTH) else if (conf->include_depth >= MAX_INCLUDE_DEPTH)
{
fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n"); fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n");
}
/* Skips to first character. */ /* Skips to first character. */
while (isspace(*line)) while (isspace(*line))
line++; line++;
char *key = (char*)malloc(9);
size_t cur_size = 8;
size_t index = 0;
while (isgraph(*line)) while (isgraph(*line))
{ {
if (index == cur_size) if (index == cur_size)
{ {
cur_size *= 2; cur_size *= 2;
key = (char*)realloc(key, cur_size + 1); key_tmp = (char*)realloc(key, cur_size + 1);
if (key_tmp)
{
key = key_tmp;
}
else
{
free(key);
return false;
}
} }
key[index++] = *line++; key[index++] = *line++;
@ -365,7 +400,16 @@ static config_file_t *config_file_new_internal(
{ {
struct config_entry_list *list = (struct config_entry_list*) struct config_entry_list *list = (struct config_entry_list*)
calloc(1, sizeof(*list)); calloc(1, sizeof(*list));
char *line = getaline(file); char *line = NULL;
if (!list)
{
config_file_free(conf);
fclose(file);
return NULL;
}
line = getaline(file);
if (line) if (line)
{ {
@ -375,6 +419,7 @@ static config_file_t *config_file_new_internal(
conf->tail->next = list; conf->tail->next = list;
else else
conf->entries = list; conf->entries = list;
conf->tail = list; conf->tail = list;
} }
@ -410,9 +455,14 @@ config_file_t *config_file_new_from_string(const char *from_string)
{ {
struct config_entry_list *list = (struct config_entry_list*) struct config_entry_list *list = (struct config_entry_list*)
calloc(1, sizeof(*list)); calloc(1, sizeof(*list));
char* line = lines->elems[i].data; char* line = lines->elems[i].data;
if (!list)
{
config_file_free(conf);
return NULL;
}
if (line) if (line)
{ {
if (parse_line(conf, list, line)) if (parse_line(conf, list, line))
@ -421,6 +471,7 @@ config_file_t *config_file_new_from_string(const char *from_string)
conf->tail->next = list; conf->tail->next = list;
else else
conf->entries = list; conf->entries = list;
conf->tail = list; conf->tail = list;
} }
} }
@ -703,6 +754,10 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
struct config_entry_list *elem = (struct config_entry_list*) struct config_entry_list *elem = (struct config_entry_list*)
calloc(1, sizeof(*elem)); calloc(1, sizeof(*elem));
if (!elem)
return;
elem->key = strdup(key); elem->key = strdup(key);
elem->value = strdup(val); elem->value = strdup(val);