diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2014-03-25 14:58:00 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2014-03-25 14:58:00 +0100 |
commit | 0c3d9dacafdb807d2101c67610969707353f434a (patch) | |
tree | 4abd0f7a4178332150791bda73c5f3185a403dc7 /conf/cf-lex.l | |
parent | 4e7c974d22ee5d938d8d8e7018f0a63f609d630b (diff) |
Fixes file descriptor leak when parser ends with error.
Thanks to MrBr for the bugreport.
Diffstat (limited to 'conf/cf-lex.l')
-rw-r--r-- | conf/cf-lex.l | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l index b1bbeae2..99785057 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; |