]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fixes file descriptor leak when parser ends with error.
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 25 Mar 2014 13:58:00 +0000 (14:58 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 25 Mar 2014 13:58:00 +0000 (14:58 +0100)
Thanks to MrBr for the bugreport.

conf/cf-lex.l
conf/conf.c
conf/conf.h

index b1bbeae2869249e62fce82e1ca666b4d92d93307..997850575e92275ece0ab9bfe2581db7baa8a556 100644 (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)
-        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;
index 67b027cee861aa27c1a2c752c72c250f5a2dbcfa..a907402d936ef34062326ce65b196213de7ce8f8 100644 (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);
 }
 
index a8bba7e851380278bec5773be9b7f2a1fff758b2..fa14d7b50402f7746206ac9d9c6f1c3e86b45eec 100644 (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);