From d4c7182341945fe6cb1ebd4c81041d1ed4f022cb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Apr 14 2009 21:24:36 +0000 Subject: - Add last minute bug fixes, found in testing the package --- diff --git a/0001-Add-reconnection-code-between-the-NSS-responder-and.patch b/0001-Add-reconnection-code-between-the-NSS-responder-and.patch new file mode 100644 index 0000000..da000b8 --- /dev/null +++ b/0001-Add-reconnection-code-between-the-NSS-responder-and.patch @@ -0,0 +1,90 @@ +From ecd411426a6c37d842b6d390c4895f34538130cf Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Tue, 14 Apr 2009 09:24:27 -0400 +Subject: [PATCH] Add reconnection code between the NSS responder and the Data provider + +--- + server/responder/nss/nsssrv.c | 53 ++++++++++++++++++++++++++++++++++++++++- + 1 files changed, 52 insertions(+), 1 deletions(-) + +diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c +index 58b09fb..8e72a95 100644 +--- a/server/responder/nss/nsssrv.c ++++ b/server/responder/nss/nsssrv.c +@@ -219,6 +219,41 @@ done: + return ret; + } + ++static void nss_shutdown(struct resp_ctx *rctx) ++{ ++ /* TODO: Do clean-up here */ ++ ++ /* Nothing left to do but exit() */ ++ exit(0); ++} ++ ++ ++static void nss_dp_reconnect_init(struct sbus_conn_ctx *sconn, int status, void *pvt) ++{ ++ int ret; ++ struct resp_ctx *rctx = talloc_get_type(pvt, struct resp_ctx); ++ ++ /* Did we reconnect successfully? */ ++ if (status == SBUS_RECONNECT_SUCCESS) { ++ /* Add the methods back to the new connection */ ++ ret = sbus_conn_add_method_ctx(rctx->dp_ctx->scon_ctx, ++ rctx->dp_ctx->sm_ctx); ++ if (ret != EOK) { ++ DEBUG(0, ("Could not re-add methods on reconnection.\n")); ++ nss_shutdown(rctx); ++ } ++ ++ DEBUG(1, ("Reconnected to the Data Provider.\n")); ++ return; ++ } ++ ++ /* Handle failure */ ++ DEBUG(0, ("Could not reconnect to data provider.\n")); ++ /* Kill the backend and let the monitor restart it */ ++ nss_shutdown(rctx); ++} ++ ++ + int nss_process_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx *cdb) +@@ -226,7 +261,7 @@ int nss_process_init(TALLOC_CTX *mem_ctx, + struct sbus_method *nss_dp_methods; + struct sss_cmd_table *nss_cmds; + struct nss_ctx *nctx; +- int ret; ++ int ret, max_retries; + + nctx = talloc_zero(mem_ctx, struct nss_ctx); + if (!nctx) { +@@ -261,6 +296,22 @@ int nss_process_init(TALLOC_CTX *mem_ctx, + return ret; + } + ++ /* Enable automatic reconnection to the Data Provider */ ++ ++ /* FIXME: "retries" is too generic, either get it from a global config ++ * or specify these retries are about the sbus connections to DP */ ++ ret = confdb_get_int(nctx->rctx->cdb, nctx->rctx, ++ nctx->rctx->confdb_service_path, ++ "retries", 3, &max_retries); ++ if (ret != EOK) { ++ DEBUG(0, ("Failed to set up automatic reconnection\n")); ++ return ret; ++ } ++ ++ sbus_reconnect_init(nctx->rctx->dp_ctx->scon_ctx, ++ max_retries, ++ nss_dp_reconnect_init, nctx->rctx); ++ + DEBUG(1, ("NSS Initialization complete\n")); + + return EOK; +-- +1.6.0.6 + diff --git a/0003-Make-reconnection-to-the-Data-Provider-a-global-sett.patch b/0003-Make-reconnection-to-the-Data-Provider-a-global-sett.patch new file mode 100644 index 0000000..26a389e --- /dev/null +++ b/0003-Make-reconnection-to-the-Data-Provider-a-global-sett.patch @@ -0,0 +1,110 @@ +From ac5a54e24ac79a33ddf8320811d981b950e21e8e Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Tue, 14 Apr 2009 10:22:20 -0400 +Subject: [PATCH] Make reconnection to the Data Provider a global setting + +Previously, every DP client was allowed to set its own "retries" +option. This option was ambiguous, and useless. All DP clients +will now use a global option set in the services config called +"reconnection_retries" +--- + server/confdb/confdb.h | 2 ++ + server/examples/sssd.conf | 3 +++ + server/monitor/monitor.c | 2 +- + server/providers/data_provider_be.c | 4 ++-- + server/responder/nss/nsssrv.c | 7 ++----- + server/responder/pam/pamsrv.c | 4 ++-- + 6 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h +index fda584c..19614fc 100644 +--- a/server/confdb/confdb.h ++++ b/server/confdb/confdb.h +@@ -32,6 +32,8 @@ + #define CONFDB_DEFAULT_CONFIG_FILE SSSD_CONF_DIR"/sssd.conf" + #define SSSD_MIN_ID 1000 + ++#define SERVICE_CONF_ENTRY "config/services" ++ + struct confdb_ctx; + + typedef int (*confdb_reconf_fn) (struct confdb_ctx *cdb, void *pvt); +diff --git a/server/examples/sssd.conf b/server/examples/sssd.conf +index b9a421e..a480b54 100644 +--- a/server/examples/sssd.conf ++++ b/server/examples/sssd.conf +@@ -1,6 +1,9 @@ + [services] + description = Local Service Configuration + activeServices = nss, dp, pam ++# Number of times services should attempt to reconnect in the ++# event of a Data Provider crash or restart before they give up ++reconnection_retries = 3 + + [services/nss] + description = NSS Responder Configuration +diff --git a/server/monitor/monitor.c b/server/monitor/monitor.c +index 69640b9..dd80830 100644 +--- a/server/monitor/monitor.c ++++ b/server/monitor/monitor.c +@@ -558,7 +558,7 @@ int get_monitor_config(struct mt_ctx *ctx) + } + + ret = confdb_get_string(ctx->cdb, ctx, +- "config/services", "activeServices", ++ SERVICE_CONF_ENTRY, "activeServices", + NULL, &svcs); + + if (ret != EOK || svcs == NULL) { +diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c +index 3d824c3..6cd86e8 100644 +--- a/server/providers/data_provider_be.c ++++ b/server/providers/data_provider_be.c +@@ -681,8 +681,8 @@ static int be_cli_init(struct be_ctx *ctx) + } + + /* Enable automatic reconnection to the Data Provider */ +- ret = confdb_get_int(ctx->cdb, ctx, ctx->conf_path, +- "retries", 3, &max_retries); ++ ret = confdb_get_int(ctx->cdb, ctx, SERVICE_CONF_ENTRY, ++ "reconnection_retries", 3, &max_retries); + if (ret != EOK) { + DEBUG(0, ("Failed to set up automatic reconnection\n")); + return ret; +diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c +index 8e72a95..e85e56b 100644 +--- a/server/responder/nss/nsssrv.c ++++ b/server/responder/nss/nsssrv.c +@@ -297,12 +297,9 @@ int nss_process_init(TALLOC_CTX *mem_ctx, + } + + /* Enable automatic reconnection to the Data Provider */ +- +- /* FIXME: "retries" is too generic, either get it from a global config +- * or specify these retries are about the sbus connections to DP */ + ret = confdb_get_int(nctx->rctx->cdb, nctx->rctx, +- nctx->rctx->confdb_service_path, +- "retries", 3, &max_retries); ++ SERVICE_CONF_ENTRY, ++ "reconnection_retries", 3, &max_retries); + if (ret != EOK) { + DEBUG(0, ("Failed to set up automatic reconnection\n")); + return ret; +diff --git a/server/responder/pam/pamsrv.c b/server/responder/pam/pamsrv.c +index 1adbb14..e4ddc43 100644 +--- a/server/responder/pam/pamsrv.c ++++ b/server/responder/pam/pamsrv.c +@@ -163,8 +163,8 @@ static int pam_process_init(struct main_context *main_ctx, + + /* FIXME: "retries" is too generic, either get it from a global config + * or specify these retries are about the sbus connections to DP */ +- ret = confdb_get_int(rctx->cdb, rctx, rctx->confdb_service_path, +- "retries", 3, &max_retries); ++ ret = confdb_get_int(rctx->cdb, rctx, SERVICE_CONF_ENTRY, ++ "reconnection_retries", 3, &max_retries); + if (ret != EOK) { + DEBUG(0, ("Failed to set up automatic reconnection\n")); + return ret; +-- +1.6.0.6 + diff --git a/0004-Add-common-function-to-retrieve-comma-sep.-lists.patch b/0004-Add-common-function-to-retrieve-comma-sep.-lists.patch new file mode 100644 index 0000000..ff336aa --- /dev/null +++ b/0004-Add-common-function-to-retrieve-comma-sep.-lists.patch @@ -0,0 +1,426 @@ +From 4ad7fe5e6acc87140fc29b635605af8445d2d32f Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Tue, 14 Apr 2009 11:20:30 -0400 +Subject: [PATCH] Add common function to retrieve comma sep. lists + +Also convert all places where we were using custom code to parse +config arguments. +And fix a copy&paste error in nss_get_config +--- + server/confdb/confdb.c | 203 ++++++++++++++++++++++++++++++++--------- + server/confdb/confdb.h | 4 + + server/monitor/monitor.c | 54 +---------- + server/responder/nss/nsssrv.c | 24 +++-- + 4 files changed, 179 insertions(+), 106 deletions(-) + +diff --git a/server/confdb/confdb.c b/server/confdb/confdb.c +index d3a2a08..1f642ca 100644 +--- a/server/confdb/confdb.c ++++ b/server/confdb/confdb.c +@@ -36,8 +36,8 @@ + #include "ini_config.h" + + #define CONFDB_VERSION "1" +-#define CONFDB_BASEDN "cn=config" +-#define CONFDB_DOMAIN_BASEDN "cn=domains,"CONFDB_BASEDN ++#define CONFDB_DOMAINS_PATH "config/domains" ++#define CONFDB_DOMAIN_BASEDN "cn=domains,cn=config" + #define CONFDB_DOMAIN_ATTR "cn" + #define CONFDB_MPG "magicPrivateGroups" + #define CONFDB_FQ "useFullyQualifiedNames" +@@ -121,6 +121,110 @@ done: + return ret; + } + ++/* split a string into an allocated array of strings. ++ * the separator is a string, and is case-sensitive. ++ * optionally single values can be trimmed of of spaces and tabs */ ++static int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, ++ char *sep, bool trim, char ***_list, int *size) ++{ ++ const char *t, *p, *n; ++ size_t l, s, len; ++ char **list, **r; ++ ++ if (!str || !*str || !sep || !*sep || !_list) return EINVAL; ++ ++ s = strlen(sep); ++ t = str; ++ ++ list = NULL; ++ l = 0; ++ ++ if (trim) ++ while (*t == ' ' || *t == '\t') t++; ++ ++ while (t && (p = strstr(t, sep))) { ++ len = p - t; ++ n = p + s; /* save next string starting point */ ++ if (trim) { ++ while (*t == ' ' || *t == '\t') { ++ t++; ++ len--; ++ if (len == 0) break; ++ } ++ p--; ++ while (len > 0 && (*p == ' ' || *p == '\t')) { ++ len--; ++ p--; ++ } ++ } ++ ++ r = talloc_realloc(mem_ctx, list, char *, l + 2); ++ if (!r) { ++ talloc_free(list); ++ return ENOMEM; ++ } else { ++ list = r; ++ } ++ ++ if (len == 0) { ++ list[l] = talloc_strdup(list, ""); ++ } else { ++ list[l] = talloc_strndup(list, t, len); ++ } ++ if (!list[l]) { ++ talloc_free(list); ++ return ENOMEM; ++ } ++ l++; ++ ++ t = n; /* move to next string */ ++ } ++ ++ if (t) { ++ r = talloc_realloc(mem_ctx, list, char *, l + 2); ++ if (!r) { ++ talloc_free(list); ++ return ENOMEM; ++ } else { ++ list = r; ++ } ++ ++ if (trim) { ++ len = strlen(t); ++ while (*t == ' ' || *t == '\t') { ++ t++; ++ len--; ++ if (len == 0) break; ++ } ++ p = t + len - 1; ++ while (len > 0 && (*p == ' ' || *p == '\t')) { ++ len--; ++ p--; ++ } ++ ++ if (len == 0) { ++ list[l] = talloc_strdup(list, ""); ++ } else { ++ list[l] = talloc_strndup(list, t, len); ++ } ++ } else { ++ list[l] = talloc_strdup(list, t); ++ } ++ if (!list[l]) { ++ talloc_free(list); ++ return ENOMEM; ++ } ++ l++; ++ } ++ ++ list[l] = NULL; /* terminate list */ ++ ++ if (size) *size = l + 1; ++ *_list = list; ++ ++ return EOK; ++} ++ + int confdb_add_param(struct confdb_ctx *cdb, + bool replace, + const char *section, +@@ -496,6 +600,43 @@ failed: + return ret; + } + ++/* WARNING: Unlike other similar functions, this one does NOT take a default, ++ * and returns ENOENT if the attribute was not found ! */ ++int confdb_get_string_as_list(struct confdb_ctx *cdb, TALLOC_CTX *ctx, ++ const char *section, const char *attribute, ++ char ***result) ++{ ++ char **values = NULL; ++ int ret; ++ ++ ret = confdb_get_param(cdb, ctx, section, attribute, &values); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ if (values && values[0]) { ++ if (values[1] != NULL) { ++ /* too many values */ ++ ret = EINVAL; ++ goto done; ++ } ++ } else { ++ /* Did not return a value */ ++ ret = ENOENT; ++ goto done; ++ } ++ ++ ret = split_on_separator(ctx, values[0], ",", true, result, NULL); ++ ++done: ++ talloc_free(values); ++ if (ret != EOK && ret != ENOENT) { ++ DEBUG(2, ("Failed to get [%s] from [%s], error [%d] (%s)", ++ attribute, section, ret, strerror(ret))); ++ } ++ return ret; ++} ++ + int confdb_test(struct confdb_ctx *cdb) + { + char **values; +@@ -948,61 +1089,33 @@ int confdb_get_domains(struct confdb_ctx *cdb, + struct sss_domain_info **domains) + { + TALLOC_CTX *tmp_ctx; +- struct ldb_dn *dn; +- struct ldb_result *res; + struct sss_domain_info *domain, *prevdom; + struct sss_domain_info *first = NULL; +- const char *attrs[] = { "domains", NULL }; +- const char *tmp; +- char *cur, *p, *t; +- int ret; ++ char **domlist; ++ int ret, i; + + tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) return ENOMEM; + +- dn = ldb_dn_new(tmp_ctx, cdb->ldb, CONFDB_DOMAIN_BASEDN); +- if (!dn) { +- ret = EIO; +- goto done; +- } +- +- ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, +- LDB_SCOPE_BASE, attrs, NULL); +- if (ret != LDB_SUCCESS) { +- ret = EIO; +- goto done; +- } +- +- if (res->count != 1) { +- ret = EFAULT; ++ ret = confdb_get_string_as_list(cdb, tmp_ctx, ++ CONFDB_DOMAINS_PATH, "domains", &domlist); ++ if (ret == ENOENT) { ++ DEBUG(0, ("No domains configured, fatal error!\n")); + goto done; + } +- +- tmp = ldb_msg_find_attr_as_string(res->msgs[0], "domains", NULL); +- if (!tmp) { +- DEBUG(0, ("No domains configured, fatal error!\n")); +- ret = EINVAL; ++ if (ret != EOK ) { ++ DEBUG(0, ("Fatal error retrieving domains list!\n")); + goto done; + } +- cur = p = talloc_strdup(tmp_ctx, tmp); + +- while (p && *p) { +- +- for (cur = p; (*cur == ' ' || *cur == '\t'); cur++) /* trim */ ; +- if (!*cur) break; +- +- p = strchr(cur, ','); +- if (p) { +- /* terminate element */ +- *p = '\0'; +- /* trim spaces */ +- for (t = p-1; (*t == ' ' || *t == '\t'); t--) *t = '\0'; +- p++; ++ for (i = 0; domlist[i]; i++) { ++ ret = confdb_get_domain(cdb, mem_ctx, domlist[i], &domain); ++ if (ret) { ++ DEBUG(0, ("Error (%d [%s]) retrieving domain %s, skipping!\n", ++ ret, strerror(ret), domains[i])); ++ continue; + } + +- ret = confdb_get_domain(cdb, mem_ctx, cur, &domain); +- if (ret) goto done; +- + if (first == NULL) { + first = domain; + prevdom = first; +@@ -1014,7 +1127,7 @@ int confdb_get_domains(struct confdb_ctx *cdb, + + if (first == NULL) { + DEBUG(0, ("No domains configured, fatal error!\n")); +- ret = EINVAL; ++ ret = ENOENT; + } + + *domains = first; +diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h +index 19614fc..76e4482 100644 +--- a/server/confdb/confdb.h ++++ b/server/confdb/confdb.h +@@ -80,6 +80,10 @@ int confdb_get_bool(struct confdb_ctx *cdb, TALLOC_CTX *ctx, + const char *section, const char *attribute, + bool defval, bool *result); + ++int confdb_get_string_as_list(struct confdb_ctx *cdb, TALLOC_CTX *ctx, ++ const char *section, const char *attribute, ++ char ***result); ++ + int confdb_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx **cdb_ctx, +diff --git a/server/monitor/monitor.c b/server/monitor/monitor.c +index dd80830..20734d1 100644 +--- a/server/monitor/monitor.c ++++ b/server/monitor/monitor.c +@@ -544,11 +544,6 @@ static int service_signal_reload(struct mt_svc *svc) + int get_monitor_config(struct mt_ctx *ctx) + { + int ret; +- size_t svc_count = 0; +- char *svcs; +- char *cur, *p, *t; +- char **svc_list = NULL; +- char **tmp_list = NULL; + + ret = confdb_get_int(ctx->cdb, ctx, + MONITOR_CONF_ENTRY, "sbusTimeout", +@@ -557,61 +552,20 @@ int get_monitor_config(struct mt_ctx *ctx) + return ret; + } + +- ret = confdb_get_string(ctx->cdb, ctx, +- SERVICE_CONF_ENTRY, "activeServices", +- NULL, &svcs); +- +- if (ret != EOK || svcs == NULL) { ++ ret = confdb_get_string_as_list(ctx->cdb, ctx, SERVICE_CONF_ENTRY, ++ "activeServices", &ctx->services); ++ if (ret != EOK) { + DEBUG(0, ("No services configured!\n")); + return EINVAL; + } + +- cur = p = talloc_strdup(svcs, svcs); +- while (p && *p) { +- for (cur = p; (*cur == ' ' || *cur == '\t'); cur++) /* trim */ ; +- if (!*cur) break; +- +- p = strchr(cur, ','); +- if (p) { +- /* terminate element */ +- *p = '\0'; +- /* trim spaces */ +- for (t = p-1; (*t == ' ' || *t == '\t'); t--) *t = '\0'; +- p++; +- } +- +- svc_count++; +- tmp_list = talloc_realloc(svcs, svc_list, char *, svc_count); +- if (!tmp_list) { +- ret = ENOMEM; +- goto done; +- } +- svc_list = tmp_list; +- svc_list[svc_count-1] = talloc_strdup(svc_list, cur); +- } +- +- svc_count++; +- tmp_list = talloc_realloc(svcs, svc_list, char *, svc_count); +- if (!tmp_list) { +- ret = ENOMEM; +- goto done; +- } +- svc_list = tmp_list; +- svc_list[svc_count-1] = NULL; +- +- ctx->services = talloc_steal(ctx, svc_list); +- + ret = confdb_get_domains(ctx->cdb, ctx, &ctx->domains); + if (ret != EOK) { + DEBUG(2, ("No domains configured. LOCAL should always exist!\n")); + return ret; + } + +- ret = EOK; +- +-done: +- talloc_free(svcs); +- return ret; ++ return EOK; + } + + static int get_service_config(struct mt_ctx *ctx, const char *name, +diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c +index e85e56b..e04a8c8 100644 +--- a/server/responder/nss/nsssrv.c ++++ b/server/responder/nss/nsssrv.c +@@ -138,18 +138,20 @@ static int nss_get_config(struct nss_ctx *nctx, + + ret = confdb_get_int(cdb, nctx, NSS_SRV_CONFIG, + "EntryCacheTimeout", 600, +- &nctx->enum_cache_timeout); ++ &nctx->cache_timeout); + if (ret != EOK) goto done; + + ret = confdb_get_int(cdb, nctx, NSS_SRV_CONFIG, + "EntryNegativeTimeout", 15, +- &nctx->enum_cache_timeout); ++ &nctx->neg_timeout); + if (ret != EOK) goto done; + +- ret = confdb_get_param(cdb, nctx, NSS_SRV_CONFIG, +- "filterUsers", &filter_list); +- if (ret != EOK) goto done; +- for (i = 0; filter_list[i]; i++) { ++ ret = confdb_get_string_as_list(cdb, tmpctx, NSS_SRV_CONFIG, ++ "filterUsers", &filter_list); ++ if (ret == ENOENT) filter_list = NULL; ++ else if (ret != EOK) goto done; ++ ++ for (i = 0; (filter_list && filter_list[i]); i++) { + ret = sss_parse_name(tmpctx, nctx->rctx->names, + filter_list[i], &domain, &name); + if (ret != EOK) { +@@ -178,11 +180,12 @@ static int nss_get_config(struct nss_ctx *nctx, + } + } + } +- talloc_free(filter_list); + +- ret = confdb_get_param(cdb, nctx, NSS_SRV_CONFIG, +- "filterGroups", &filter_list); +- if (ret != EOK) goto done; ++ ret = confdb_get_string_as_list(cdb, tmpctx, NSS_SRV_CONFIG, ++ "filterGroups", &filter_list); ++ if (ret == ENOENT) filter_list = NULL; ++ else if (ret != EOK) goto done; ++ + for (i = 0; filter_list[i]; i++) { + ret = sss_parse_name(tmpctx, nctx->rctx->names, + filter_list[i], &domain, &name); +@@ -212,7 +215,6 @@ static int nss_get_config(struct nss_ctx *nctx, + } + } + } +- talloc_free(filter_list); + + done: + talloc_free(tmpctx); +-- +1.6.0.6 + diff --git a/0005-Fixing-memory-issues-in-ini-and-collection.patch b/0005-Fixing-memory-issues-in-ini-and-collection.patch new file mode 100644 index 0000000..d7b909f --- /dev/null +++ b/0005-Fixing-memory-issues-in-ini-and-collection.patch @@ -0,0 +1,217 @@ +From 9fc454c84d539cd90aed3a74a350bdc792455407 Mon Sep 17 00:00:00 2001 +From: Dmitri Pal +Date: Tue, 14 Apr 2009 14:55:42 -0400 +Subject: [PATCH] Fixing memory issues in ini and collection + +The read_line() function used an internal buffer allocated on stack +as temporary storage for a line read from file, then returned it. +read_line() now gets a buffer from the caller. +Fixed memory leaks in INI and Collection found by valgrind. +--- + common/collection/collection_ut.c | 15 +++++++++------ + common/ini/ini_config.c | 36 +++++++++++++++++++++++++++++------- + common/ini/ini_config_ut.c | 4 ++-- + 3 files changed, 40 insertions(+), 15 deletions(-) + +diff --git a/common/collection/collection_ut.c b/common/collection/collection_ut.c +index 6d27db6..eabf522 100644 +--- a/common/collection/collection_ut.c ++++ b/common/collection/collection_ut.c +@@ -480,6 +480,7 @@ int mixed_collection_test() + /* Traverse collection again - peer should still be there */ + error = print_collection(event); + if(error) { ++ destroy_collection(event); + printf("Error printing collection %d\n",error); + return error; + } +@@ -488,18 +489,17 @@ int mixed_collection_test() + + error = debug_collection(event,COL_TRAVERSE_DEFAULT); + if(error) { ++ destroy_collection(event); + printf("Error printing collection %d\n",error); + return error; + } + + printf("Attempt to add property to a referenced collection.\n"); + +- /* Some negative tests */ +- /* Can't add attributes to the referenced collection */ + error = add_int_property(event,"host","session",500); +- if(error != 0) printf("Error was NOT able to add property to a referenced collection.\n"); +- else { +- printf("Unexpected success which is an implementation error.\n"); ++ if(error) { ++ destroy_collection(event); ++ printf("Error was NOT able to add property to a referenced collection %d.\n", error); + return error; + } + +@@ -508,6 +508,7 @@ int mixed_collection_test() + /* Can't delete non exitent property */ + error = delete_property(event,"host.host",COL_TYPE_ANY, COL_TRAVERSE_DEFAULT); + if(error == 0) { ++ destroy_collection(event); + printf("Error was able to delete property that does not exist.\n"); + return -1; + } +@@ -516,12 +517,14 @@ int mixed_collection_test() + /* Set collection class */ + error = set_collection_class(event,2); + if(error != 0) { ++ destroy_collection(event); + printf("Error was NOT able to set class.\n"); + return error; + } + + error = get_collection_class(event,&class); + if(error != 0) { ++ destroy_collection(event); + printf("Error was NOT able to get class.\n"); + return error; + } +@@ -529,6 +532,7 @@ int mixed_collection_test() + + if(is_of_class(event,2)) printf("Class mathced!\n"); + else { ++ destroy_collection(event); + printf("Error - bad class.\n"); + return -1; + } +@@ -706,4 +710,3 @@ int main() + /* Add other tests here ... */ + return error; + } +- +diff --git a/common/ini/ini_config.c b/common/ini/ini_config.c +index 4112049..fd1efb0 100644 +--- a/common/ini/ini_config.c ++++ b/common/ini/ini_config.c +@@ -83,8 +83,14 @@ inline const char *parsing_error_str(int parsing_error) + return str_error[parsing_error-1]; + } + +- +-int read_line(FILE *file,char **key,char **value, int *length, int *ext_error); ++/* Internal function to read line from INI file */ ++int read_line(FILE *file, ++ char *buf, ++ int read_size, ++ char **key, ++ char **value, ++ int *length, ++ int *ext_error); + + /* Add to collection or update - CONSIDER moving to the collection.c */ + static int add_or_update(struct collection_item *current_section, +@@ -137,6 +143,8 @@ static int ini_to_collection(const char *filename, + struct parse_error pe; + int line = 0; + int created = 0; ++ char buf[BUFFER_SIZE+1]; ++ + + TRACE_FLOW_STRING("ini_to_collection", "Entry"); + +@@ -162,7 +170,8 @@ static int ini_to_collection(const char *filename, + + /* Read file lines */ + while (1) { +- status = read_line(file, &key, &value, &length, &ext_err); ++ /* Always read one less than the buffer */ ++ status = read_line(file, buf, BUFFER_SIZE+1, &key, &value, &length, &ext_err); + if (status == RET_EOF) break; + + line++; +@@ -505,11 +514,15 @@ int config_for_app(const char *application, + } + + /* Reads a line from the file */ +-int read_line(FILE *file, char **key,char **value, int *length, int *ext_error) ++int read_line(FILE *file, ++ char *buf, ++ int read_size, ++ char **key, char **value, ++ int *length, ++ int *ext_error) + { + + char *res; +- char buf[BUFFER_SIZE+1]; + int len; + char *buffer; + int i; +@@ -522,12 +535,15 @@ int read_line(FILE *file, char **key,char **value, int *length, int *ext_error) + buffer = buf; + + /* Get data from file */ +- res = fgets(buffer, BUFFER_SIZE, file); ++ res = fgets(buffer, read_size - 1, file); + if (res == NULL) { + TRACE_ERROR_STRING("Read nothing", ""); + return RET_EOF; + } + ++ /* Make sure the buffer is NULL terminated */ ++ buffer[read_size - 1] = '\0'; ++ + len = strlen(buffer); + if (len == 0) { + TRACE_ERROR_STRING("Nothing was read.", ""); +@@ -550,7 +566,8 @@ int read_line(FILE *file, char **key,char **value, int *length, int *ext_error) + TRACE_INFO_STRING("BUFFER before trimming:", buffer); + + /* Trucate trailing spaces and CRs */ +- while (isspace(buffer[len - 1])) { ++ /* Make sure not to step before the beginning */ ++ while (len && isspace(buffer[len - 1])) { + buffer[len - 1] = '\0'; + len--; + } +@@ -847,6 +864,9 @@ int get_config_item(const char *section, + error = get_item(section_handle, name, + COL_TYPE_STRING, COL_TRAVERSE_ONELEVEL, item); + ++ /* Make sure we free the section we found */ ++ destroy_collection(section_handle); ++ + TRACE_FLOW_NUMBER("get_config_item returning", error); + return error; + } +@@ -1521,6 +1541,8 @@ char **get_attribute_list(struct collection_item *ini_config, const char *sectio + /* Pass it to the function from collection API */ + list = collection_to_list(subcollection, size, error); + ++ destroy_collection(subcollection); ++ + TRACE_FLOW_STRING("get_attribute_list returning", list == NULL ? "NULL" : list[0]); + return list; + } +diff --git a/common/ini/ini_config_ut.c b/common/ini/ini_config_ut.c +index 6787c36..5441e02 100644 +--- a/common/ini/ini_config_ut.c ++++ b/common/ini/ini_config_ut.c +@@ -303,7 +303,6 @@ int get_test() + + debug_item(item); + +- + printf("Get item as string without duplication from NULL item.\n"); + + /* Get a string without duplicication */ +@@ -759,9 +758,10 @@ int get_test() + return -1; + } + +- for (i=0;i - 0.3.1-2 +- Add last minute bug fixes, found in testing the package + * Mon Apr 13 2009 Simo Sorce - 0.3.1-1 - Version 0.3.1 - includes previous release patches