Commit 0c3d9dac authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

Fixes file descriptor leak when parser ends with error.

Thanks to MrBr for the bugreport.
parent 4e7c974d
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
}

+2 −0
Original line number Diff line number Diff line
@@ -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);