]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Allow floating and negative values in expressions limits
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 18 Nov 2017 15:31:11 +0000 (15:31 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 18 Nov 2017 15:31:11 +0000 (15:31 +0000)
src/libserver/composites.c
src/libutil/expression.c

index cfb8968ff480ed66d302ca3f43d21d5189433731..3f74683ed73b07ed652b1ec5a49d040304749fe9 100644 (file)
@@ -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,
index a6b0153d9400eb6a8d647d82cc56ef8f863f6026..0a55647887fbb2061f449a87950a4cffc3e816e0 100644 (file)
@@ -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);