From c684e3f3c3be00deaa3ea287db86b047d02aebc9 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 4 Mar 2009 13:26:19 -0800 Subject: [PATCH] classifier: Allow classifier_for_each_match() callback to free the rule. classifier_for_each_match() would segfault if the callback passed in deleted and freed the rule in question, because it accessed the rule after calling the callback. This commit should fix the problem. Thanks to Natasha for reporting the problem. --- lib/classifier.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/classifier.c b/lib/classifier.c index 5081823d..ddc5bf0e 100644 --- a/lib/classifier.c +++ b/lib/classifier.c @@ -347,6 +347,9 @@ classifier_for_each_match(const struct classifier *cls, const struct cls_rule *target, int include, cls_cb_func *cb, void *aux) { + struct cls_rule *prev_rule; + + prev_rule = NULL; if (include & CLS_INC_WILD) { const struct hmap *table; for (table = &cls->tables[0]; table < &cls->tables[CLS_N_FIELDS]; @@ -361,7 +364,10 @@ classifier_for_each_match(const struct classifier *cls, LIST_FOR_EACH (pos, struct cls_rule, node.list, &bucket->rules) { if (rules_match_1wild(pos, target, 0)) { - cb(pos, aux); + if (prev_rule) { + cb(prev_rule, aux); + } + prev_rule = pos; } } } @@ -374,7 +380,10 @@ classifier_for_each_match(const struct classifier *cls, HMAP_FOR_EACH (rule, struct cls_rule, node.hmap, &cls->exact_table) { if (rules_match_1wild(rule, target, 0)) { - cb(rule, aux); + if (prev_rule) { + cb(prev_rule, aux); + } + prev_rule = rule; } } } else { @@ -384,10 +393,16 @@ classifier_for_each_match(const struct classifier *cls, struct cls_rule *rule = search_exact_table(cls, hash, &target->flow); if (rule) { - cb(rule, aux); + if (prev_rule) { + cb(prev_rule, aux); + } + prev_rule = rule; } } } + if (prev_rule) { + cb(prev_rule, aux); + } } void -- 2.30.2