From cd8e2fb4ebd25184c097462296f07c0082190e14 Mon Sep 17 00:00:00 2001 From: Jan Kadlec <jan.kadlec@nic.cz> Date: Sun, 1 Sep 2013 00:09:04 +0200 Subject: [PATCH] dnssec: Custom free function for (possibly) merged changesets Refs #4 --- src/knot/server/zones.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c index 7047b2a70..a955458e6 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -1077,6 +1077,40 @@ static bool zones_changesets_empty(const knot_changesets_t *chs) return knot_changeset_is_empty(HEAD(chs->sets)); } +static void zones_free_merged_changesets(knot_changesets_t *diff_chs, + knot_changesets_t *sec_chs) +{ + /* + * \todo Merged changesets freeing can be quite complicated, since there + * are several cases to handle. It might be easier to free the single + * changeset in the changesets structures when there are no changes in it, but + * that would require some extra return codes. Still, probably better than this. + */ + if (diff_chs == NULL && + sec_chs == NULL) { + } else if (diff_chs == NULL && + sec_chs != NULL) { + knot_changesets_free(&sec_chs); + } else if (sec_chs == NULL && + diff_chs != NULL) { + knot_changesets_free(&diff_chs); + } else { + /* + * Merged changesets, deep free 'diff_chs', + * shallow free 'sec_chs', unless one of them is empty. + */ + if (zones_changesets_empty(sec_chs) || zones_changesets_empty(diff_chs)) { + knot_changesets_free(&sec_chs); + knot_changesets_free(&diff_chs); + } else { + knot_changesets_free(&diff_chs); + // Reset sec_chs' changeset list, else we have double free. + init_list(&sec_chs->sets); + knot_changesets_free(&sec_chs); + } + } +} + static int zones_merge_and_store_changesets(knot_zone_t *zone, knot_changesets_t *diff_chs, knot_changesets_t *sec_chs) @@ -1453,8 +1487,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst, ret = xfrin_apply_changesets(zone, sec_chs, &new_contents); if (ret != KNOT_EOK) { - knot_changesets_free(&diff_chs); - knot_changesets_free(&sec_chs); + zones_free_merged_changesets(diff_chs, sec_chs); rcu_read_unlock(); return ret; } @@ -1466,8 +1499,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst, ret = xfrin_switch_zone(zone, new_contents, XFR_TYPE_DNSSEC); if (ret != KNOT_EOK) { - knot_changesets_free(&diff_chs); - knot_changesets_free(&sec_chs); + zones_free_merged_changesets(diff_chs, sec_chs); rcu_read_unlock(); return ret; } @@ -1477,6 +1509,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst, ret = KNOT_ENODIFF; } + zones_free_merged_changesets(diff_chs, sec_chs); rcu_read_unlock(); } -- GitLab