From: Ben Pfaff Date: Wed, 4 Mar 2009 21:26:19 +0000 (-0800) Subject: classifier: Allow classifier_for_each_match() callback to free the rule. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c684e3f3c3be00deaa3ea287db86b047d02aebc9;p=openvswitch 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. --- 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