aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-11-18 15:31:11 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-11-18 15:31:11 +0000
commitf6363ae05cabffc99d4081eb2f525d4633b5fcb0 (patch)
tree9d254ee12fd5d736e62f02fcda0d42aedb18de1c /src
parent2e4d88630e57f0e4c3e111a22734a6f98366b245 (diff)
downloadrspamd-f6363ae05cabffc99d4081eb2f525d4633b5fcb0.tar.gz
rspamd-f6363ae05cabffc99d4081eb2f525d4633b5fcb0.zip
[Feature] Allow floating and negative values in expressions limits
Diffstat (limited to 'src')
-rw-r--r--src/libserver/composites.c38
-rw-r--r--src/libutil/expression.c24
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);