Fixes file descriptor leak when parser ends with error.

Thanks to MrBr for the bugreport.
This commit is contained in:
Ondrej Zajicek 2014-03-25 14:58:00 +01:00
parent 4e7c974d22
commit 0c3d9dacaf
3 changed files with 31 additions and 5 deletions

View file

@ -275,9 +275,6 @@ cf_hash(byte *c)
* match - these do not have fd and flex buffer yet).
*
* FIXME: Most of these ifs and include functions are really sysdep/unix.
*
* FIXME: Resources (fd, flex buffers and glob data) in IFS stack
* are not freed when cf_error() is called.
*/
static struct include_file_stack *
@ -316,13 +313,36 @@ enter_ifs(struct include_file_stack *new)
yy_switch_to_buffer(new->buffer);
}
/**
* cf_lex_unwind - unwind lexer state during error
*
* cf_lex_unwind() frees the internal state on IFS stack when the lexical
* analyzer is terminated by cf_error().
*/
void
cf_lex_unwind(void)
{
struct include_file_stack *n;
for (n = ifs; n != ifs_head; n = n->prev)
{
/* Memory is freed automatically */
if (n->buffer)
yy_delete_buffer(n->buffer);
if (n->fd)
close(n->fd);
}
ifs = ifs_head;
}
static void
cf_include(char *arg, int alen)
{
struct include_file_stack *base_ifs = ifs;
int new_depth, rv, i;
char *patt;
glob_t g;
glob_t g = {};
new_depth = ifs->depth + 1;
if (new_depth > MAX_INCLUDE_DEPTH)
@ -370,7 +390,10 @@ cf_include(char *arg, int alen)
struct stat fs;
if (stat(fname, &fs) < 0)
{
globfree(&g);
cf_error("Unable to stat included file %s: %m", fname);
}
if (fs.st_mode & S_IFDIR)
continue;

View file

@ -502,6 +502,7 @@ cf_error(char *msg, ...)
new_config->err_msg = cfg_strdup(buf);
new_config->err_lino = ifs->lino;
new_config->err_file_name = ifs->file_name;
cf_lex_unwind();
longjmp(conf_jmpbuf, 1);
}

View file

@ -139,6 +139,8 @@ extern struct include_file_stack *ifs;
int cf_lex(void);
void cf_lex_init(int is_cli, struct config *c);
void cf_lex_unwind(void);
struct symbol *cf_find_symbol(byte *c);
struct symbol *cf_default_name(char *template, int *counter);
struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);