From f6363ae05cabffc99d4081eb2f525d4633b5fcb0 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 18 Nov 2017 15:31:11 +0000 Subject: [PATCH] [Feature] Allow floating and negative values in expressions limits --- src/libserver/composites.c | 38 +++++++++++++++++++++++++++++--------- src/libutil/expression.c | 24 ++++++++++++------------ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/libserver/composites.c b/src/libserver/composites.c index cfb8968ff..3f74683ed 100644 --- a/src/libserver/composites.c +++ b/src/libserver/composites.c @@ -90,12 +90,12 @@ rspamd_composite_expr_parse (const gchar *line, gsize len, return res; } -static gint +static gdouble rspamd_composite_process_single_symbol (struct composites_data *cd, const gchar *sym, struct rspamd_symbol_result **pms) { struct rspamd_symbol_result *ms = NULL; - gint rc = 0; + gdouble rc = 0; struct rspamd_composite *ncomp; if ((ms = g_hash_table_lookup (cd->metric_res->symbols, sym)) == NULL) { @@ -109,7 +109,7 @@ rspamd_composite_process_single_symbol (struct composites_data *cd, RSPAMD_EXPRESSION_FLAG_NOOPT, cd); clrbit (cd->checked, cd->composite->id * 2); - if (rc) { + if (rc != 0) { setbit (cd->checked, ncomp->id * 2 + 1); ms = g_hash_table_lookup (cd->metric_res->symbols, sym); } @@ -120,12 +120,20 @@ rspamd_composite_process_single_symbol (struct composites_data *cd, /* * XXX: in case of cyclic references this would return 0 */ - rc = isset (cd->checked, ncomp->id * 2 + 1); + if (isset (cd->checked, ncomp->id * 2 + 1)) { + ms = g_hash_table_lookup (cd->metric_res->symbols, sym); + } } } } - else { - rc = 1; + + if (ms) { + if (ms->score == 0) { + rc = 0.001; /* Distinguish from 0 */ + } + else { + rc = ms->score; + } } *pms = ms; @@ -144,11 +152,23 @@ rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom) struct rspamd_symbol *sdef; GHashTableIter it; gpointer k, v; - gint rc = 0; + gdouble rc = 0; if (isset (cd->checked, cd->composite->id * 2)) { /* We have already checked this composite, so just return its value */ - rc = isset (cd->checked, cd->composite->id * 2 + 1); + if (isset (cd->checked, cd->composite->id * 2 + 1)) { + ms = g_hash_table_lookup (cd->metric_res->symbols, sym); + } + + if (ms) { + if (ms->score == 0) { + rc = 0.001; /* Distinguish from 0 */ + } + else { + rc = ms->score; + } + } + return rc; } @@ -178,7 +198,7 @@ rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom) rc = rspamd_composite_process_single_symbol (cd, sym, &ms); } - if (rc && ms) { + if (rc != 0 && ms) { /* * At this point we know that we need to do something about this symbol, * however, we don't know whether we need to delete it unfortunately, diff --git a/src/libutil/expression.c b/src/libutil/expression.c index a6b0153d9..0a5564788 100644 --- a/src/libutil/expression.c +++ b/src/libutil/expression.c @@ -40,14 +40,12 @@ struct rspamd_expression_elt { union { rspamd_expression_atom_t *atom; enum rspamd_expression_op op; - struct { - gint val; - gint op_idx; - } lim; + gdouble lim; } p; + gint flags; - gdouble value; gint priority; + gdouble value; }; struct rspamd_expression { @@ -593,7 +591,8 @@ rspamd_parse_expression (const gchar *line, gsize len, } memset (&elt, 0, sizeof (elt)); - num_re = rspamd_regexp_cache_create (NULL, "/^\\d+(?:\\s+|[)]|$)/", NULL, NULL); + num_re = rspamd_regexp_cache_create (NULL, + "/^(?:[+-]?([0-9]*[.])?[0-9]+)(?:\\s+|[)]|$)/", NULL, NULL); p = line; c = line; @@ -689,7 +688,8 @@ rspamd_parse_expression (const gchar *line, gsize len, } break; case PARSE_LIM: - if (g_ascii_isdigit (*p) && p != end - 1) { + if ((g_ascii_isdigit (*p) || *p == '-' || *p == '.') + && p < end - 1) { p ++; } else { @@ -699,7 +699,7 @@ rspamd_parse_expression (const gchar *line, gsize len, if (p - c > 0) { elt.type = ELT_LIMIT; - elt.p.lim.val = strtoul (c, NULL, 10); + elt.p.lim = strtod (c, NULL); g_array_append_val (e->expressions, elt); rspamd_expr_stack_elt_push (operand_stack, g_node_new (rspamd_expr_dup_elt (pool, &elt))); @@ -1033,7 +1033,7 @@ rspamd_ast_process_node (struct rspamd_expression *expr, gint flags, GNode *node break; case ELT_LIMIT: - acc = elt->p.lim.val; + acc = elt->p.lim; break; case ELT_OP: g_assert (node->children != NULL); @@ -1044,7 +1044,7 @@ rspamd_ast_process_node (struct rspamd_expression *expr, gint flags, GNode *node celt = node->parent->children->data; if (celt->type == ELT_LIMIT) { - lim = celt->p.lim.val; + lim = celt->p.lim; } } @@ -1053,7 +1053,7 @@ rspamd_ast_process_node (struct rspamd_expression *expr, gint flags, GNode *node /* Save limit if we've found it */ if (celt->type == ELT_LIMIT) { - lim = celt->p.lim.val; + lim = celt->p.lim; continue; } @@ -1144,7 +1144,7 @@ rspamd_ast_string_traverse (GNode *n, gpointer d) (int)elt->p.atom->len, elt->p.atom->str); } else if (elt->type == ELT_LIMIT) { - rspamd_printf_gstring (res, "%d", elt->p.lim.val); + rspamd_printf_gstring (res, "%f", elt->p.lim); } else { op_str = rspamd_expr_op_to_str (elt->p.op); -- 2.39.5