summaryrefslogtreecommitdiff
path: root/conf/cf-lex.l
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2015-11-09 00:42:02 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2015-11-09 00:42:02 +0100
commit9b9a7143c43d01f0459d40363d56e9c7690c596f (patch)
tree45571f60f4e3582cd4c0c17c3f1de1c3a2da35dc /conf/cf-lex.l
parent3aed0a6ff7b2b811a535202fd787281d2ac33409 (diff)
Conf: Fixes bug in symbol lookup during reconfiguration
Symbol lookup by cf_find_symbol() not only did the lookup but also added new void symbols allocated from cfg_mem linpool, which gets broken when lookups are done outside of config parsing, which may lead to crashes during reconfiguration. The patch separates lookup-only cf_find_symbol() and config-modifying cf_get_symbol(), while the later is called only during parsing. Also new_config and cfg_mem global variables are NULLed outside of parsing.
Diffstat (limited to 'conf/cf-lex.l')
-rw-r--r--conf/cf-lex.l64
1 files changed, 43 insertions, 21 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 61e04075..5a2a4d6b 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -70,7 +70,7 @@ struct sym_scope {
static struct sym_scope *conf_this_scope;
static int cf_hash(byte *c);
-static struct symbol *cf_find_sym(byte *c, unsigned int h0);
+static inline struct symbol * cf_get_sym(byte *c, uint h0);
linpool *cfg_mem;
@@ -194,7 +194,7 @@ else: {
}
k=k->next;
}
- cf_lval.s = cf_find_sym(yytext, h);
+ cf_lval.s = cf_get_sym(yytext, h);
return SYM;
}
@@ -426,8 +426,9 @@ check_eof(void)
}
static struct symbol *
-cf_new_sym(byte *c, unsigned int h)
+cf_new_sym(byte *c, uint h0)
{
+ uint h = h0 & (SYM_HASH_SIZE-1);
struct symbol *s, **ht;
int l;
@@ -449,56 +450,77 @@ cf_new_sym(byte *c, unsigned int h)
}
static struct symbol *
-cf_find_sym(byte *c, unsigned int h0)
+cf_find_sym(struct config *cfg, byte *c, uint h0)
{
- unsigned int h = h0 & (SYM_HASH_SIZE-1);
+ uint h = h0 & (SYM_HASH_SIZE-1);
struct symbol *s, **ht;
- if (ht = new_config->sym_hash)
+ if (ht = cfg->sym_hash)
{
for(s = ht[h]; s; s=s->next)
if (!strcmp(s->name, c) && s->scope->active)
return s;
}
- if (new_config->sym_fallback)
+ if (ht = cfg->sym_fallback)
{
/* We know only top-level scope is active */
- for(s = new_config->sym_fallback[h]; s; s=s->next)
+ for(s = ht[h]; s; s=s->next)
if (!strcmp(s->name, c) && s->scope->active)
return s;
}
- return cf_new_sym(c, h);
+
+ return NULL;
+}
+
+static inline struct symbol *
+cf_get_sym(byte *c, uint h0)
+{
+ return cf_find_sym(new_config, c, h0) ?: cf_new_sym(c, h0);
}
/**
* cf_find_symbol - find a symbol by name
+ * @cfg: specificed config
+ * @c: symbol name
+ *
+ * This functions searches the symbol table in the config @cfg for a symbol of
+ * given name. First it examines the current scope, then the second recent one
+ * and so on until it either finds the symbol and returns a pointer to its
+ * &symbol structure or reaches the end of the scope chain and returns %NULL to
+ * signify no match.
+ */
+struct symbol *
+cf_find_symbol(struct config *cfg, byte *c)
+{
+ return cf_find_sym(cfg, c, cf_hash(c));
+}
+
+/**
+ * cf_get_symbol - get a symbol by name
* @c: symbol name
*
- * This functions searches the symbol table for a symbol of given
- * name. First it examines the current scope, then the second recent
- * one and so on until it either finds the symbol and returns a pointer
- * to its &symbol structure or reaches the end of the scope chain
- * and returns %NULL to signify no match.
+ * This functions searches the symbol table of the currently parsed config
+ * (@new_config) for a symbol of given name. It returns either the already
+ * existing symbol or a newly allocated undefined (%SYM_VOID) symbol if no
+ * existing symbol is found.
*/
struct symbol *
-cf_find_symbol(byte *c)
+cf_get_symbol(byte *c)
{
- return cf_find_sym(c, cf_hash(c));
+ return cf_get_sym(c, cf_hash(c));
}
struct symbol *
cf_default_name(char *template, int *counter)
{
- char buf[32];
+ char buf[SYM_MAX_LEN];
struct symbol *s;
char *perc = strchr(template, '%');
for(;;)
{
bsprintf(buf, template, ++(*counter));
- s = cf_find_sym(buf, cf_hash(buf));
- if (!s)
- break;
+ s = cf_get_sym(buf, cf_hash(buf));
if (s->class == SYM_VOID)
return s;
if (!perc)
@@ -529,7 +551,7 @@ cf_define_symbol(struct symbol *sym, int type, void *def)
{
if (sym->scope == conf_this_scope)
cf_error("Symbol already defined");
- sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
+ sym = cf_new_sym(sym->name, cf_hash(sym->name));
}
sym->class = type;
sym->def = def;