diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2015-11-09 00:42:02 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2015-11-09 00:42:02 +0100 |
commit | 9b9a7143c43d01f0459d40363d56e9c7690c596f (patch) | |
tree | 45571f60f4e3582cd4c0c17c3f1de1c3a2da35dc /conf/cf-lex.l | |
parent | 3aed0a6ff7b2b811a535202fd787281d2ac33409 (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.l | 64 |
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; |