When ebtRulesAppend failed its realloc, it was free'ing the argv it
had been send, but not the rules. The caller also didn't free the
rules.
This is kind of a lost cause, since it's a leak that only occurs after
a failure to allocate memory, but the fix also gives the ebtRuleFree
function a more accurate name (ebtRuleClear), and I was making a
change to this code anyway, so I split out the bugfix for easy review.
---
src/util/ebtables.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/src/util/ebtables.c b/src/util/ebtables.c
index f1b2986..d3a8432 100644
--- a/src/util/ebtables.c
+++ b/src/util/ebtables.c
@@ -94,7 +94,7 @@ enum {
};
static void
-ebtRuleFree(ebtRule *rule)
+ebtRuleClear(ebtRule *rule)
{
VIR_FREE(rule->rule);
@@ -112,20 +112,13 @@ ebtRulesAppend(ebtRules *rules,
const char **argv,
int command_idx)
{
+ ebtRule tmp = { .rule = rule, .argv = argv, .command_idx = command_idx };
+
if (VIR_REALLOC_N(rules->rules, rules->nrules+1) < 0) {
- int i = 0;
- while (argv[i])
- VIR_FREE(argv[i++]);
- VIR_FREE(argv);
+ ebtRuleClear(&tmp);
return ENOMEM;
}
-
- rules->rules[rules->nrules].rule = rule;
- rules->rules[rules->nrules].argv = argv;
- rules->rules[rules->nrules].command_idx = command_idx;
-
- rules->nrules++;
-
+ rules->rules[rules->nrules++] = tmp;
return 0;
}
@@ -142,7 +135,7 @@ ebtRulesRemove(ebtRules *rules,
if (i >= rules->nrules)
return EINVAL;
- ebtRuleFree(&rules->rules[i]);
+ ebtRuleClear(&rules->rules[i]);
memmove(&rules->rules[i],
&rules->rules[i+1],
@@ -163,7 +156,7 @@ ebtRulesFree(ebtRules *rules)
if (rules->rules) {
for (i = 0; i < rules->nrules; i++)
- ebtRuleFree(&rules->rules[i]);
+ ebtRuleClear(&rules->rules[i]);
VIR_FREE(rules->rules);
--
1.7.11.7