Fixes file descriptor leak when parser ends with error.
Thanks to MrBr for the bugreport.
This commit is contained in:
parent
4e7c974d22
commit
0c3d9dacaf
3 changed files with 31 additions and 5 deletions
|
@ -275,9 +275,6 @@ cf_hash(byte *c)
|
||||||
* match - these do not have fd and flex buffer yet).
|
* match - these do not have fd and flex buffer yet).
|
||||||
*
|
*
|
||||||
* FIXME: Most of these ifs and include functions are really sysdep/unix.
|
* 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 *
|
static struct include_file_stack *
|
||||||
|
@ -316,13 +313,36 @@ enter_ifs(struct include_file_stack *new)
|
||||||
yy_switch_to_buffer(new->buffer);
|
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
|
static void
|
||||||
cf_include(char *arg, int alen)
|
cf_include(char *arg, int alen)
|
||||||
{
|
{
|
||||||
struct include_file_stack *base_ifs = ifs;
|
struct include_file_stack *base_ifs = ifs;
|
||||||
int new_depth, rv, i;
|
int new_depth, rv, i;
|
||||||
char *patt;
|
char *patt;
|
||||||
glob_t g;
|
glob_t g = {};
|
||||||
|
|
||||||
new_depth = ifs->depth + 1;
|
new_depth = ifs->depth + 1;
|
||||||
if (new_depth > MAX_INCLUDE_DEPTH)
|
if (new_depth > MAX_INCLUDE_DEPTH)
|
||||||
|
@ -370,7 +390,10 @@ cf_include(char *arg, int alen)
|
||||||
struct stat fs;
|
struct stat fs;
|
||||||
|
|
||||||
if (stat(fname, &fs) < 0)
|
if (stat(fname, &fs) < 0)
|
||||||
|
{
|
||||||
|
globfree(&g);
|
||||||
cf_error("Unable to stat included file %s: %m", fname);
|
cf_error("Unable to stat included file %s: %m", fname);
|
||||||
|
}
|
||||||
|
|
||||||
if (fs.st_mode & S_IFDIR)
|
if (fs.st_mode & S_IFDIR)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -502,6 +502,7 @@ cf_error(char *msg, ...)
|
||||||
new_config->err_msg = cfg_strdup(buf);
|
new_config->err_msg = cfg_strdup(buf);
|
||||||
new_config->err_lino = ifs->lino;
|
new_config->err_lino = ifs->lino;
|
||||||
new_config->err_file_name = ifs->file_name;
|
new_config->err_file_name = ifs->file_name;
|
||||||
|
cf_lex_unwind();
|
||||||
longjmp(conf_jmpbuf, 1);
|
longjmp(conf_jmpbuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,8 @@ extern struct include_file_stack *ifs;
|
||||||
|
|
||||||
int cf_lex(void);
|
int cf_lex(void);
|
||||||
void cf_lex_init(int is_cli, struct config *c);
|
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_find_symbol(byte *c);
|
||||||
struct symbol *cf_default_name(char *template, int *counter);
|
struct symbol *cf_default_name(char *template, int *counter);
|
||||||
struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
|
struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
|
||||||
|
|
Loading…
Reference in a new issue