commit 3f3633edc3b454d5dd2cb22f90b6fe257d2086e9 Author: cjwatson Commit: cjwatson * Fix a bunch of reference-counting bugs and other memory leaks. git-svn-id: svn+ssh://svn.debian.org/svn/d-i/trunk@47682 48c42b26-1dd6-0310-b98f-a58d8bce7237 diff --git a/packages/cdebconf/debian/changelog b/packages/cdebconf/debian/changelog index fa4d3bb..0a9cb17 100644 --- a/packages/cdebconf/debian/changelog +++ b/packages/cdebconf/debian/changelog @@ -16,6 +16,7 @@ cdebconf (0.117) UNRELEASED; urgency=low * Fix off-by-one error reading from confmodule (thanks, Baruch Even; closes: #430108). * Document proposed PROGRESS REGION command. + * Fix a bunch of reference-counting bugs and other memory leaks. -- Attilio Fiandrotti Mon, 18 Jun 2007 15:35:11 +0200 diff --git a/packages/cdebconf/src/commands.c b/packages/cdebconf/src/commands.c index 3023003..b1d0a40 100644 --- a/packages/cdebconf/src/commands.c +++ b/packages/cdebconf/src/commands.c @@ -395,8 +395,9 @@ command_register(struct confmodule *mod, char *arg) } question_owner_add(q, mod->owner); q->template = t; - template_ref(t); + /* steal reference from mod->templates->methods.get above */ mod->questions->methods.set(mod->questions, q); + question_deref(q); asprintf(&out, "%u", CMDSTATUS_SUCCESS); return out; } @@ -418,6 +419,7 @@ command_unregister(struct confmodule *mod, char *arg) return out; } question_owner_delete(q, mod->owner); + question_deref(q); asprintf(&out, "%u", CMDSTATUS_SUCCESS); return out; @@ -458,6 +460,8 @@ command_metaget(struct confmodule *mod, char *arg) asprintf(&out, "%u %s", CMDSTATUS_SUCCESS, value); free(value); + question_deref(q); + return out; } @@ -596,6 +600,7 @@ command_x_loadtemplatefile(struct confmodule *mod, char *arg) if (*argv[1]) question_owner_add(q, argv[1]); mod->questions->methods.set(mod->questions, q); + question_deref(q); t = t->next; } asprintf(&out, "%u OK", CMDSTATUS_SUCCESS); @@ -638,6 +643,7 @@ command_progress(struct confmodule *mod, char *arg) return out; } value = question_get_field(q, "", "description"); + question_deref(q); if (value == NULL) { asprintf(&out, "%u %s description field does not exist", @@ -681,6 +687,7 @@ command_progress(struct confmodule *mod, char *arg) return out; } value = question_get_field(q, "", "description"); + question_deref(q); if (value == NULL) { asprintf(&out, "%u %s description field does not exist", @@ -723,6 +730,7 @@ command_settitle(struct confmodule *mod, char *arg) return out; } value = question_get_field(q, "", "description"); + question_deref(q); if (value == NULL) { asprintf(&out, "%u %s description field does not exist", @@ -774,6 +782,7 @@ command_info(struct confmodule *mod, char *arg) return out; } mod->frontend->methods.info(mod->frontend, q); + question_deref(q); asprintf(&out, "%u OK", CMDSTATUS_SUCCESS); return out; @@ -814,9 +823,11 @@ command_data(struct confmodule *mod, char *arg) } template_lset(t, NULL, item, value); mod->questions->methods.set(mod->questions, q); + question_deref(q); } else template_lset(t, NULL, item, value); + template_deref(t); asprintf(&out, "%u OK", CMDSTATUS_SUCCESS); return out; diff --git a/packages/cdebconf/src/configuration.c b/packages/cdebconf/src/configuration.c index 9aa8305..3ce33aa 100644 --- a/packages/cdebconf/src/configuration.c +++ b/packages/cdebconf/src/configuration.c @@ -181,6 +181,7 @@ static int config_read(struct configuration *cfg, const char *filename) unsigned int stackpos = 0; int curline = 0, i; int incomment = 0, inquote = 0; + int ret = DC_OK; linebuf[0] = 0; parenttag[0] = 0; @@ -309,7 +310,8 @@ static int config_read(struct configuration *cfg, const char *filename) if (termchar == '{' && linebuf[0] == 0) { INFO(INFO_ERROR, "Syntax error %s:%u: block starts with no name", filename, curline); - return DC_NOTOK; + ret = DC_NOTOK; + goto out; } if (linebuf[0] == 0) @@ -331,7 +333,8 @@ static int config_read(struct configuration *cfg, const char *filename) && strparsequoteword(&q, tag, sizeof(tag)) == 0) { INFO(INFO_ERROR, "Syntax error %s:%u: Malformed tag", filename, curline); - return DC_NOTOK; + ret = DC_NOTOK; + goto out; } /* parse off the value */ @@ -350,15 +353,18 @@ static int config_read(struct configuration *cfg, const char *filename) if (strlen(q) != 0) { INFO(INFO_ERROR, "Syntax error %s:%u: Extra junk after tag", filename, curline); - return DC_NOTOK; + ret = DC_NOTOK; + goto out; } if (termchar == '{') { /* 99, not 100. 100 gives possible off-by-one error */ - if (stackpos <= 99) + if (stackpos <= 99) { + DELETE(stack[stackpos]); stack[stackpos++] = strdup(parenttag); + } if (value[0] != 0) { strvacat(tag, sizeof(tag), @@ -423,8 +429,11 @@ static int config_read(struct configuration *cfg, const char *filename) strvacat(linebuf, sizeof(linebuf), " ", (char *) 0); strcat(linebuf, buf); } +out: fclose(infp); - return DC_OK; + for (i = 0; i < DIM(stack); i++) + DELETE(stack[i]); + return ret; } static void config_dump(struct configuration *cfg) @@ -489,6 +498,8 @@ void config_delete(struct configuration *config) while (top != 0 && top->next == 0) { next = top->parent; + DELETE(top->tag); + DELETE(top->value); DELETE(top); top = next; } @@ -496,8 +507,12 @@ void config_delete(struct configuration *config) if (top != 0) { next = top->next; + DELETE(top->tag); + DELETE(top->value); DELETE(top); top = next; } } + + DELETE(config); } diff --git a/packages/cdebconf/src/database.c b/packages/cdebconf/src/database.c index ecaedbd..9ea076d 100644 --- a/packages/cdebconf/src/database.c +++ b/packages/cdebconf/src/database.c @@ -130,9 +130,9 @@ struct template_db *template_db_new(struct configuration *cfg, struct template_db_module *mod; char tmp[256]; const char *modpath, *modname, *driver; - + if (instance != NULL) { - modname = strdup(instance); + modname = instance; } else { modname = cfg->get(cfg, "global::default::template", getenv("DEBCONF_TEMPLATE")); } @@ -160,7 +160,7 @@ struct template_db *template_db_new(struct configuration *cfg, db = NEW(struct template_db); memset(db, 0, sizeof(struct template_db)); db->handle = dlh; - db->modname = modname; + db->modname = STRDUP(modname); db->data = NULL; db->config = cfg; snprintf(db->configpath, sizeof(db->configpath), @@ -196,7 +196,8 @@ struct template_db *template_db_new(struct configuration *cfg, void template_db_delete(struct template_db *db) { db->methods.shutdown(db); - dlclose(db->handle); + free(db->modname); + /* dlclose(db->handle); */ DELETE(db); } @@ -376,8 +377,8 @@ struct question_db *question_db_new(struct configuration *cfg, const char *modpath, *driver, *modname = NULL; if (instance != NULL) - modname = strdup(instance); - + modname = instance; + if (modname == NULL) modname = getenv("DEBCONF_CONFIG"); @@ -407,7 +408,7 @@ struct question_db *question_db_new(struct configuration *cfg, db = NEW(struct question_db); memset(db, 0, sizeof(struct question_db)); db->handle = dlh; - db->modname = modname; + db->modname = STRDUP(modname); db->data = NULL; db->config = cfg; db->tdb = tdb; @@ -447,7 +448,8 @@ struct question_db *question_db_new(struct configuration *cfg, void question_db_delete(struct question_db *db) { db->methods.shutdown(db); - dlclose(db->handle); + free(db->modname); + /* dlclose(db->handle); */ DELETE(db); } diff --git a/packages/cdebconf/src/database.h b/packages/cdebconf/src/database.h index 6e7d535..abcbf13 100644 --- a/packages/cdebconf/src/database.h +++ b/packages/cdebconf/src/database.h @@ -57,7 +57,7 @@ struct question_db_module { */ struct template_db { /** db module name */ - const char *modname; + char *modname; /** db module handle */ void *handle; /** configuration data */ @@ -76,7 +76,7 @@ struct template_db { */ struct question_db { /** db module name */ - const char *modname; + char *modname; /** db module handle */ void *handle; /** configuration data */ diff --git a/packages/cdebconf/src/debconf-loadtemplate.c b/packages/cdebconf/src/debconf-loadtemplate.c index 85acf2b..91a04ec 100644 --- a/packages/cdebconf/src/debconf-loadtemplate.c +++ b/packages/cdebconf/src/debconf-loadtemplate.c @@ -122,6 +122,8 @@ int main(int argc, char **argv) if (tdb->methods.set(tdb, t) != DC_OK) INFO(INFO_ERROR, "Cannot add template %s", t->tag); } + if (oldt) + template_deref(oldt); q = qdb->methods.get(qdb, t->tag); if (q == NULL) @@ -140,7 +142,9 @@ int main(int argc, char **argv) if (qdb->methods.set(qdb, q) != DC_OK) INFO(INFO_ERROR, "Cannot add config %s", t->tag); question_deref(q); + oldt = t; t = t->next; + template_deref(oldt); } } diff --git a/packages/cdebconf/src/frontend.c b/packages/cdebconf/src/frontend.c index 2ed0823..7dba994 100644 --- a/packages/cdebconf/src/frontend.c +++ b/packages/cdebconf/src/frontend.c @@ -83,6 +83,7 @@ static void frontend_info(struct frontend *f, struct question *info) { question_deref(f->info); f->info = info; + question_ref(info); } static bool frontend_can_go_back(struct frontend *ui, struct question *q) @@ -232,10 +233,10 @@ void frontend_delete(struct frontend *obj) obj->methods.shutdown(obj); if (obj->handle != NULL) dlclose(obj->handle); - DELETE(obj->questions); + frontend_clear(obj); DELETE(obj->capb); DELETE(obj->title); - DELETE(obj->info); + question_deref(obj->info); DELETE(obj->progress_title); DELETE(obj->plugin_path); DELETE(obj); diff --git a/packages/cdebconf/src/modules/db/http/http.c b/packages/cdebconf/src/modules/db/http/http.c index e61428e..a867daa 100644 --- a/packages/cdebconf/src/modules/db/http/http.c +++ b/packages/cdebconf/src/modules/db/http/http.c @@ -208,6 +208,22 @@ static int http_template_initialize(struct template_db *db, struct configuration return DC_OK; } +static int http_template_shutdown(struct template_db *db) +{ + struct template_db_cache *dbdata = db->data; + struct template *t; + + while (dbdata->templates != NULL) + { + t = dbdata->templates; + dbdata->templates = dbdata->templates->next; + t->next = NULL; + template_deref(t); + } + + return DC_OK; +} + static int http_template_set(struct template_db *db, struct template *t) { return DC_NOTIMPL; @@ -280,6 +296,22 @@ static int http_question_initialize(struct question_db *db, struct configuration return DC_OK; } +static int http_question_shutdown(struct question_db *db) +{ + struct question_db_cache *dbdata = db->data; + struct question *q; + + while (dbdata->questions != NULL) + { + q = dbdata->questions; + dbdata->questions = dbdata->questions->next; + q->next = q->prev = NULL; + question_deref(q); + } + + return DC_OK; +} + static int http_question_set(struct question_db *db, struct question *q) { return DC_NOTIMPL; @@ -363,6 +395,7 @@ static struct question *http_question_iterate(struct question_db *db, struct template_db_module debconf_template_db_module = { initialize: http_template_initialize, + shutdown: http_template_shutdown, set: http_template_set, get: http_template_get, remove: http_template_remove, @@ -371,6 +404,7 @@ struct template_db_module debconf_template_db_module = { struct question_db_module debconf_question_db_module = { initialize: http_question_initialize, + shutdown: http_question_shutdown, set: http_question_set, get: http_question_get, disown: http_question_disown, diff --git a/packages/cdebconf/src/modules/db/rfc822db/rfc822db.c b/packages/cdebconf/src/modules/db/rfc822db/rfc822db.c index d4cdb62..353b578 100644 --- a/packages/cdebconf/src/modules/db/rfc822db/rfc822db.c +++ b/packages/cdebconf/src/modules/db/rfc822db/rfc822db.c @@ -22,6 +22,9 @@ FILE *outf = NULL; +static struct template *rfc822db_template_get(struct template_db *db, + const char *ltag); + int nodetemplatecomp(const void *pa, const void *pb) { return strcmp(((struct template *)pa)->tag, ((struct template *)pb)->tag); @@ -125,6 +128,11 @@ static int parse_flags(char *string) return ret; } +void rfc822db_template_destroyitem(void *data) +{ + template_deref((struct template *) data); +} + /* templates */ static int rfc822db_template_initialize(struct template_db *db, struct configuration *cfg) { @@ -142,6 +150,20 @@ static int rfc822db_template_initialize(struct template_db *db, struct configura return DC_OK; } +static int rfc822db_template_shutdown(struct template_db *db) +{ + struct template_db_cache *dbdata = db->data; + if (dbdata == NULL) + return DC_OK; + if (dbdata->root) + tdestroy(dbdata->root, rfc822db_template_destroyitem); + if (dbdata->iterator) + di_slist_destroy(dbdata->iterator, rfc822db_template_destroyitem); + free(dbdata); + db->data = NULL; + return DC_OK; +} + /* * Function: rfc822db_template_load * Input: template database @@ -356,11 +378,6 @@ void rfc822db_template_makeiterator(const void *nodep, const VISIT which, template_dup(*(struct template **) nodep)); } -void rfc822db_template_destroyiterator(void *data) -{ - template_deref((struct template *) data); -} - static struct template *rfc822db_template_iterate(struct template_db *db, void **iter) { @@ -373,8 +390,7 @@ static struct template *rfc822db_template_iterate(struct template_db *db, node = *(di_slist_node **) iter; if (node == NULL) { if (dbdata->iterator) - di_slist_destroy(dbdata->iterator, - rfc822db_template_destroyiterator); + di_slist_destroy(dbdata->iterator, rfc822db_template_destroyitem); dbdata->iterator = di_slist_alloc(); template_iterator = dbdata->iterator; /* non-thread-safe */ twalk(dbdata->root, rfc822db_template_makeiterator); @@ -384,7 +400,7 @@ static struct template *rfc822db_template_iterate(struct template_db *db, *iter = node = node->next; if (node == NULL) { - di_slist_destroy(dbdata->iterator, rfc822db_template_destroyiterator); + di_slist_destroy(dbdata->iterator, rfc822db_template_destroyitem); dbdata->iterator = NULL; return NULL; } @@ -394,6 +410,11 @@ static struct template *rfc822db_template_iterate(struct template_db *db, return t; } +void rfc822db_question_destroyitem(void *data) +{ + question_deref((struct question *) data); +} + /* config database */ static int rfc822db_question_initialize(struct question_db *db, struct configuration *cfg) { @@ -412,6 +433,20 @@ static int rfc822db_question_initialize(struct question_db *db, struct configura return DC_OK; } +static int rfc822db_question_shutdown(struct question_db *db) +{ + struct question_db_cache *dbdata = db->data; + if (dbdata == NULL) + return DC_OK; + if (dbdata->root) + tdestroy(dbdata->root, rfc822db_question_destroyitem); + if (dbdata->iterator) + di_slist_destroy(dbdata->iterator, rfc822db_question_destroyitem); + free(dbdata); + db->data = NULL; + return DC_OK; +} + /* * Function: rfc822db_question_load * Input: question database @@ -668,11 +703,6 @@ void rfc822db_question_makeiterator(const void *nodep, const VISIT which, question_dup(*(struct question **) nodep)); } -void rfc822db_question_destroyiterator(void *data) -{ - question_deref((struct question *) data); -} - static struct question *rfc822db_question_iterate(struct question_db *db, void **iter) { @@ -685,8 +715,7 @@ static struct question *rfc822db_question_iterate(struct question_db *db, node = *(di_slist_node **) iter; if (node == NULL) { if (dbdata->iterator) - di_slist_destroy(dbdata->iterator, - rfc822db_question_destroyiterator); + di_slist_destroy(dbdata->iterator, rfc822db_question_destroyitem); dbdata->iterator = di_slist_alloc(); question_iterator = dbdata->iterator; /* non-thread-safe */ twalk(dbdata->root, rfc822db_question_makeiterator); @@ -696,7 +725,7 @@ static struct question *rfc822db_question_iterate(struct question_db *db, *iter = node = node->next; if (node == NULL) { - di_slist_destroy(dbdata->iterator, rfc822db_question_destroyiterator); + di_slist_destroy(dbdata->iterator, rfc822db_question_destroyitem); dbdata->iterator = NULL; return NULL; } @@ -708,6 +737,7 @@ static struct question *rfc822db_question_iterate(struct question_db *db, struct template_db_module debconf_template_db_module = { initialize: rfc822db_template_initialize, + shutdown: rfc822db_template_shutdown, load: rfc822db_template_load, save: rfc822db_template_save, set: rfc822db_template_set, @@ -718,6 +748,7 @@ struct template_db_module debconf_template_db_module = { struct question_db_module debconf_question_db_module = { initialize: rfc822db_question_initialize, + shutdown: rfc822db_question_shutdown, load: rfc822db_question_load, save: rfc822db_question_save, set: rfc822db_question_set, diff --git a/packages/cdebconf/src/modules/db/stack/stack.c b/packages/cdebconf/src/modules/db/stack/stack.c index 2860b7e..472ba76 100644 --- a/packages/cdebconf/src/modules/db/stack/stack.c +++ b/packages/cdebconf/src/modules/db/stack/stack.c @@ -85,10 +85,8 @@ static int stack_template_db_shutdown(struct template_db *db) struct template_stack *tstack = (struct template_stack *)db->data; while (tstack) { struct template_stack *next = tstack->next; - if (tstack->db->methods.shutdown(tstack->db) != DC_OK) - return DC_NOTOK; - dlclose(tstack->db->handle); - DELETE(tstack->db); + template_db_delete(tstack->db); + DELETE(tstack); tstack = next; } return DC_OK; @@ -250,10 +248,8 @@ static int stack_question_db_shutdown(struct question_db *db) struct question_stack *qstack = (struct question_stack *)db->data; while (qstack) { struct question_stack *next = qstack->next; - if (qstack->db->methods.shutdown(qstack->db) != DC_OK) - return DC_NOTOK; - dlclose(qstack->db->handle); - DELETE(qstack->db); + question_db_delete(qstack->db); + DELETE(qstack); qstack = next; } return DC_OK; diff --git a/packages/cdebconf/src/modules/db/textdb/textdb.c b/packages/cdebconf/src/modules/db/textdb/textdb.c index 5d81332..6c51ef1 100644 --- a/packages/cdebconf/src/modules/db/textdb/textdb.c +++ b/packages/cdebconf/src/modules/db/textdb/textdb.c @@ -114,6 +114,22 @@ static int textdb_template_initialize(struct template_db *db, struct configurati return DC_OK; } +static int textdb_template_shutdown(struct template_db *db) +{ + struct template_db_cache *dbdata = db->data; + struct template *t; + + while (dbdata->templates != NULL) + { + t = dbdata->templates; + dbdata->templates = dbdata->templates->next; + t->next = NULL; + template_deref(t); + } + + return DC_OK; +} + static int textdb_template_set(struct template_db *db, struct template *t) { FILE *outf; @@ -275,6 +291,22 @@ static int textdb_question_initialize(struct question_db *db, struct configurati return DC_OK; } +static int textdb_question_shutdown(struct question_db *db) +{ + struct question_db_cache *dbdata = db->data; + struct question *q; + + while (dbdata->questions != NULL) + { + q = dbdata->questions; + dbdata->questions = dbdata->questions->next; + q->next = q->prev = NULL; + question_deref(q); + } + + return DC_OK; +} + static int textdb_question_set(struct question_db *db, struct question *q) { FILE *outf; @@ -446,6 +478,7 @@ static struct question *textdb_question_iterate(struct question_db *db, struct template_db_module debconf_template_db_module = { initialize: textdb_template_initialize, + shutdown: textdb_template_shutdown, set: textdb_template_set, get: textdb_template_get, remove: textdb_template_remove, @@ -454,6 +487,7 @@ struct template_db_module debconf_template_db_module = { struct question_db_module debconf_question_db_module = { initialize: textdb_question_initialize, + shutdown: textdb_question_shutdown, set: textdb_question_set, get: textdb_question_get, disown: textdb_question_disown, diff --git a/packages/cdebconf/src/question.c b/packages/cdebconf/src/question.c index ba2b384..bef5f16 100644 --- a/packages/cdebconf/src/question.c +++ b/packages/cdebconf/src/question.c @@ -22,8 +22,18 @@ struct question *question_new(const char *tag) void question_delete(struct question *question) { + struct questionowner **ownerp; + + DELETE(question->tag); if (question->template) template_deref(question->template); + for (ownerp = &question->owners; *ownerp != NULL;) + { + struct questionowner *currentp = *ownerp; + *ownerp = currentp->next; + DELETE(currentp->owner); + DELETE(currentp); + } if (question->priority != NULL) free(question->priority); DELETE(question); diff --git a/packages/cdebconf/src/template.c b/packages/cdebconf/src/template.c index 7038b80..9b0995e 100644 --- a/packages/cdebconf/src/template.c +++ b/packages/cdebconf/src/template.c @@ -126,6 +126,7 @@ void template_delete(struct template *t) while (p != NULL) { q = p->next; + DELETE(p->language); DELETE(p->defaultval); DELETE(p->choices); DELETE(p->indices);