From 37ec537dd939818ce0279184ddf5c20bba391179 Mon Sep 17 00:00:00 2001 From: Giovanni Giacobbi Date: Wed, 13 Feb 2002 22:30:18 +0000 Subject: [PATCH] fixed a crashing bug in silcd/serverconfig.c now silc_config_register and silc_config_register_table return bool --- apps/silcd/serverconfig.c | 5 ++++ lib/silcutil/silcconfig.c | 50 ++++++++++++++++++++++++--------------- lib/silcutil/silcconfig.h | 19 ++++++++++----- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index 7cb2a9e5..f34616bf 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -520,6 +520,7 @@ SILC_CONFIG_CALLBACK(fetch_client) silc_free(tmp->host); my_free_authdata(tmp->passphrase, tmp->publickey); silc_free(tmp); + config->tmp = NULL; return got_errno; } @@ -584,6 +585,7 @@ SILC_CONFIG_CALLBACK(fetch_admin) silc_free(tmp->nick); my_free_authdata(tmp->passphrase, tmp->publickey); silc_free(tmp); + config->tmp = NULL; return got_errno; } @@ -636,6 +638,7 @@ SILC_CONFIG_CALLBACK(fetch_deny) silc_free(tmp->host); silc_free(tmp->reason); silc_free(tmp); + config->tmp = NULL; return got_errno; } @@ -704,6 +707,7 @@ SILC_CONFIG_CALLBACK(fetch_server) silc_free(tmp->version); my_free_authdata(tmp->passphrase, tmp->publickey); silc_free(tmp); + config->tmp = NULL; return got_errno; } @@ -783,6 +787,7 @@ SILC_CONFIG_CALLBACK(fetch_router) silc_free(tmp->backup_replace_ip); my_free_authdata(tmp->passphrase, tmp->publickey); silc_free(tmp); + config->tmp = NULL; return got_errno; } diff --git a/lib/silcutil/silcconfig.c b/lib/silcutil/silcconfig.c index 188ffa2b..8731aa1d 100644 --- a/lib/silcutil/silcconfig.c +++ b/lib/silcutil/silcconfig.c @@ -72,7 +72,7 @@ static char *errorstrs[] = { "Expected data but not found", /* SILC_CONFIG_EEXPECTED */ "Expected '='", /* SILC_CONFIG_EEXPECTEDEQUAL */ "Unexpected data", /* SILC_CONFIG_EUNEXPECTED */ - "Missing needed fields", /* SILC_CONFIG_EMISSFIELDS */ + "Missing mandatory fields", /* SILC_CONFIG_EMISSFIELDS */ "Missing ';'", /* SILC_CONFIG_EMISSCOLON */ }; @@ -377,9 +377,10 @@ static void silc_config_destroy(SilcConfigEntity ent) silc_free(ent); } -/* Registers a new option in the specified entity */ +/* Registers a new option in the specified entity. + * Returns TRUE on success, FALSE if already registered. */ -void silc_config_register(SilcConfigEntity ent, const char *name, +bool silc_config_register(SilcConfigEntity ent, const char *name, SilcConfigType type, SilcConfigCallback cb, const SilcConfigTable *subtable, void *context) { @@ -387,17 +388,18 @@ void silc_config_register(SilcConfigEntity ent, const char *name, SILC_CONFIG_DEBUG(("Register new option=\"%s\" type=%u cb=0x%08x context=0x%08x", name, type, (uint32) cb, (uint32) context)); - if (!ent || !name) - return; /* if we are registering a block, make sure there is a specified sub-table */ - if ((type == SILC_CONFIG_ARG_BLOCK) && !subtable) - return; - /* refuse special tag */ + if (!ent || !name || ((type == SILC_CONFIG_ARG_BLOCK) && !subtable)) + return FALSE; + + /* don't register a reserved tag */ if (!strcasecmp(name, "include")) - return; + return FALSE; + + /* check if an option was previously registered */ if (silc_config_find_option(ent, name)) { - fprintf(stderr, "Internal Error: Option double registered\n"); - abort(); + SILC_LOG_DEBUG(("Error: Can't register \"%s\" twice.", name)); + return FALSE; } /* allocate and append the new option */ @@ -408,6 +410,7 @@ void silc_config_register(SilcConfigEntity ent, const char *name, newopt->subtable = subtable; newopt->context = context; + /* append this option to the list */ if (!ent->opts) ent->opts = newopt; else { @@ -415,21 +418,25 @@ void silc_config_register(SilcConfigEntity ent, const char *name, for (tmp = ent->opts; tmp->next; tmp = tmp->next); tmp->next = newopt; } + return TRUE; } /* Register a new option table in the specified config entity */ -void silc_config_register_table(SilcConfigEntity ent, +bool silc_config_register_table(SilcConfigEntity ent, const SilcConfigTable table[], void *context) { int i; - if (!ent || !table) return; + if (!ent || !table) + return FALSE; SILC_CONFIG_DEBUG(("Registering table")); - /* FIXME: some potability checks needed */ + /* XXX FIXME: some potability checks needed - really? */ for (i = 0; table[i].name; i++) { - silc_config_register(ent, table[i].name, table[i].type, - table[i].callback, table[i].subtable, context); + if (!silc_config_register(ent, table[i].name, table[i].type, + table[i].callback, table[i].subtable, context)) + return FALSE; } + return TRUE; } /* ... */ @@ -544,9 +551,14 @@ static int silc_config_main_internal(SilcConfigEntity ent) /* now call block clean-up callback (if any) */ if (thisopt->cb) { - SILC_CONFIG_DEBUG(("Now calling clean-up callback (if any)")); - thisopt->cb(thisopt->type, thisopt->name, file->line, - NULL, thisopt->context); + int ret; + SILC_CONFIG_DEBUG(("Now calling clean-up callback")); + ret = thisopt->cb(thisopt->type, thisopt->name, file->line, NULL, + thisopt->context); + if (ret) { + SILC_CONFIG_DEBUG(("Callback refused the value [ret=%d]", ret)); + return ret; + } } /* Do we want ';' to be mandatory after close brace? */ if (*(*p)++ != ';') diff --git a/lib/silcutil/silcconfig.h b/lib/silcutil/silcconfig.h index 87db1cf8..13265734 100644 --- a/lib/silcutil/silcconfig.h +++ b/lib/silcutil/silcconfig.h @@ -104,7 +104,7 @@ enum { SILC_CONFIG_EEXPECTED, /* Expected data but not found */ SILC_CONFIG_EEXPECTEDEQUAL, /* Expected '=' */ SILC_CONFIG_EUNEXPECTED, /* Unexpected data */ - SILC_CONFIG_EMISSFIELDS, /* Missing needed fields */ + SILC_CONFIG_EMISSFIELDS, /* Missing mandatory fields */ SILC_CONFIG_EMISSCOLON, /* Missing ';' */ }; /***/ @@ -383,7 +383,7 @@ char *silc_config_read_current_line(SilcConfigFile *file); * * SYNOPSIS * - * void silc_config_register(SilcConfigEntity ent, const char *name, + * bool silc_config_register(SilcConfigEntity ent, const char *name, * SilcConfigType type, SilcConfigCallback cb, * const SilcConfigTable *subtable, * void *context); @@ -394,14 +394,17 @@ char *silc_config_read_current_line(SilcConfigFile *file); * will be called with the *val pointer pointing to an internally * allocated storage of type described by `type'. * If `type' is SILC_CONFIG_ARG_BLOCK, then `subtable' must be a valid - * pointer to a SilcConfigTable array specified the options in the + * pointer to a SilcConfigTable array specifying the options in the * sub-block. + * If the option `name' was already registered in this sub-block or it + * matches the reserved word "Include", then this function returns FALSE, + * otherwise it returns TRUE. * * SEE ALSO * silc_config_register_table * ***/ -void silc_config_register(SilcConfigEntity ent, const char *name, +bool silc_config_register(SilcConfigEntity ent, const char *name, SilcConfigType type, SilcConfigCallback cb, const SilcConfigTable *subtable, void *context); @@ -409,7 +412,7 @@ void silc_config_register(SilcConfigEntity ent, const char *name, * * SYNOPSIS * - * void silc_config_register_table(SilcConfigEntity ent, + * bool silc_config_register_table(SilcConfigEntity ent, * const SilcConfigTable table[], * void *context); * @@ -420,12 +423,16 @@ void silc_config_register(SilcConfigEntity ent, const char *name, * all with the same context `context'. * The `table' array must be terminated with an entry with the name field * set to NULL. + * If the table contains invalid data this function returns FALSE, otherwise + * it returns TRUE. If a calling to this function failed, you must destroy + * and recreate the entity before retrying, as it's impossible to detect + * the point at the function stopped the registering process. * * SEE ALSO * SilcConfigTable * ***/ -void silc_config_register_table(SilcConfigEntity ent, +bool silc_config_register_table(SilcConfigEntity ent, const SilcConfigTable table[], void *context); /****f* silcutil/SilcConfigAPI/silc_config_main -- 2.24.0