diff --git a/conf/cf-lex.l b/conf/cf-lex.l index b1bbeae..9978505 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -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) - cf_error("Unable to stat included file %s: %m", fname); + { + globfree(&g); + cf_error("Unable to stat included file %s: %m", fname); + } if (fs.st_mode & S_IFDIR) continue; diff --git a/conf/conf.c b/conf/conf.c index 67b027c..a907402 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -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); } diff --git a/conf/conf.h b/conf/conf.h index a8bba7e..fa14d7b 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -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);