From 67dcc6b83c9a0b2d4d4bd71bee01aa04e65b7583 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 12 May 2015 18:47:00 +0100 Subject: [PATCH] Rework composite symbols removal. Reported by: @fatalbanana --- src/libmime/filter.c | 78 +++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/src/libmime/filter.c b/src/libmime/filter.c index e8e27d3cf..b294abc36 100644 --- a/src/libmime/filter.c +++ b/src/libmime/filter.c @@ -453,6 +453,7 @@ struct symbol_remove_data { struct symbol *ms; gboolean remove_weight; gboolean remove_symbol; + GList *comp; }; @@ -501,6 +502,12 @@ rspamd_composite_process_single_symbol (struct composites_data *cd, rc = rspamd_process_expression (ncomp->expr, RSPAMD_EXPRESSION_FLAG_NOOPT, cd); clrbit (cd->checked, cd->composite->id * 2); + + if (rc) { + setbit (cd->checked, ncomp->id * 2 + 1); + } + setbit (cd->checked, ncomp->id * 2); + ms = g_hash_table_lookup (cd->metric_res->symbols, sym); } else { @@ -564,24 +571,32 @@ rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom) * that depends on the later decisions when the complete expression is * evaluated. */ - rd = rspamd_mempool_alloc (cd->task->task_pool, sizeof (*cd)); - rd->ms = ms; - if (G_UNLIKELY (t == '~')) { - rd->remove_weight = FALSE; - rd->remove_symbol = TRUE; - } - else if (G_UNLIKELY (t == '-')) { - rd->remove_symbol = FALSE; - rd->remove_weight = FALSE; - } - else { - rd->remove_symbol = TRUE; - rd->remove_weight = TRUE; - } - if (!g_tree_lookup (cd->symbols_to_remove, ms->name)) { + if ((rd = g_tree_lookup (cd->symbols_to_remove, ms->name)) == NULL) { g_tree_insert (cd->symbols_to_remove, (gpointer)ms->name, rd); + rd = rspamd_mempool_alloc (cd->task->task_pool, sizeof (*rd)); + rd->ms = ms; + if (G_UNLIKELY (t == '~')) { + rd->remove_weight = FALSE; + rd->remove_symbol = TRUE; + } + else if (G_UNLIKELY (t == '-')) { + rd->remove_symbol = FALSE; + rd->remove_weight = FALSE; + } + else { + rd->remove_symbol = TRUE; + rd->remove_weight = TRUE; + } + rd->comp = g_list_prepend (NULL, cd->composite); + } + else { + /* + * XXX: what if we have different preferences regarding + * weight and symbol removal in different composites? + */ + rd->comp = g_list_prepend (rd->comp, cd->composite); } } @@ -641,12 +656,37 @@ composites_remove_symbols (gpointer key, gpointer value, gpointer data) { struct composites_data *cd = data; struct symbol_remove_data *rd = value; + GList *cur; + struct rspamd_composite *comp; + gboolean matched = FALSE; + + cur = rd->comp; - if (rd->remove_symbol) { - g_hash_table_remove (cd->metric_res->symbols, key); + /* + * XXX: actually, this is a weak assumption as we are unaware here about + * negate operation and so on. We need to parse AST directly and remove + * only those symbols that could be removed. + */ + while (cur) { + comp = cur->data; + + if (isset (cd->checked, comp->id * 2 + 1)) { + matched = TRUE; + break; + } + + cur = g_list_next (cur); } - if (rd->remove_weight) { - cd->metric_res->score -= rd->ms->score; + + g_list_free (rd->comp); + + if (matched) { + if (rd->remove_symbol) { + g_hash_table_remove (cd->metric_res->symbols, key); + } + if (rd->remove_weight) { + cd->metric_res->score -= rd->ms->score; + } } return FALSE; -- 2.39.5