]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Allow to set negative group score limit via `min_score`
authorVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 30 Jul 2024 16:14:07 +0000 (17:14 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 30 Jul 2024 16:14:07 +0000 (17:14 +0100)
src/libmime/scan_result.c
src/libserver/cfg_file.h
src/libserver/cfg_rcl.cxx
src/libserver/cfg_utils.cxx
src/lua/lua_config.c
src/plugins/fuzzy_check.c
src/rspamadm/configdump.c

index f15290b95d434c66c997e021f15b34bbdf9d181a..bc7e5ccfd81372268e4815e534c8d98897fcfb13 100644 (file)
@@ -201,16 +201,29 @@ rspamd_check_group_score(struct rspamd_task *task,
                                                 double *group_score,
                                                 double w)
 {
-       if (gr != NULL && group_score && gr->max_score > 0.0 && w > 0.0) {
-               if (*group_score >= gr->max_score && w > 0) {
+       double group_limit = NAN;
+
+       if (gr != NULL && group_score) {
+               if ((*group_score + w) >= 0 && !isnan(gr->max_score) && gr->max_score > 0) {
+                       group_limit = gr->max_score;
+               }
+               else if ((*group_score + w) < 0 && !isnan(gr->min_score) && gr->min_score < 0) {
+                       group_limit = -gr->min_score;
+               }
+       }
+
+       if (gr != NULL && group_limit && !isnan(group_limit)) {
+               if (fabs(*group_score) >= group_limit && signbit(*group_score) == signbit(w)) {
+                       /* Cannot add more to the group */
                        msg_info_task("maximum group score %.2f for group %s has been reached,"
                                                  " ignoring symbol %s with weight %.2f",
-                                                 gr->max_score,
+                                                 group_limit,
                                                  gr->name, symbol, w);
                        return NAN;
                }
-               else if (*group_score + w > gr->max_score) {
-                       w = gr->max_score - *group_score;
+               else if (fabs(*group_score + w) > group_limit) {
+                       /* Reduce weight */
+                       w = signbit(w) ? -group_limit - *group_score : group_limit - *group_score;
                }
        }
 
index 1ba1d84ad699f490f27c22ad98b1a527e6f840c7..fa784f2a2f4988b6188ee73424a53f7aa1a697ae 100644 (file)
@@ -102,6 +102,7 @@ struct rspamd_symbols_group {
        char *description;
        GHashTable *symbols;
        double max_score;
+       double min_score;
        unsigned int flags;
 };
 
index 8a479fa6d8d4fe6d9c493a04a348dd3a27feb5c5..9b6e759bba6ef0fea140467b85ee6ee2ae37b81a 100644 (file)
@@ -420,6 +420,18 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
                return FALSE;
        }
 
+       if (!std::isnan(gr->max_score) && gr->max_score < 0) {
+               msg_err_config("group %s has negative max_score which is broken, use min_score if required", gr->name);
+
+               return FALSE;
+       }
+       if (!std::isnan(gr->min_score) && gr->min_score > 0) {
+               msg_err_config("group %s has positive min_score which is broken, use max_score if required", gr->name);
+
+               return FALSE;
+       }
+
+
        if (const auto *elt = ucl_object_lookup(obj, "one_shot"); elt != nullptr) {
                if (ucl_object_type(elt) != UCL_BOOLEAN) {
                        g_set_error(err,
@@ -2349,6 +2361,12 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
                                                                           G_STRUCT_OFFSET(struct rspamd_symbols_group, max_score),
                                                                           0,
                                                                           "Maximum score that could be reached by this symbols group");
+               rspamd_rcl_add_default_handler(sub,
+                                                                          "min_score",
+                                                                          rspamd_rcl_parse_struct_double,
+                                                                          G_STRUCT_OFFSET(struct rspamd_symbols_group, min_score),
+                                                                          0,
+                                                                          "Maximum negative score that could be reached by this symbols group");
        }
 
        if (!(skip_sections && g_hash_table_lookup(skip_sections, "worker"))) {
index 1344bc4f9f0cb6a382109ec4b633bd05c90d6347..d8696e72d87eb83949434af5909e913ba1a86edb 100644 (file)
@@ -1052,6 +1052,8 @@ rspamd_config_new_group(struct rspamd_config *cfg, const char *name)
        rspamd_mempool_add_destructor(cfg->cfg_pool,
                                                                  (rspamd_mempool_destruct_t) g_hash_table_unref, gr->symbols);
        gr->name = rspamd_mempool_strdup(cfg->cfg_pool, name);
+       gr->max_score = NAN;
+       gr->min_score = NAN;
 
        if (strcmp(gr->name, "ungrouped") == 0) {
                gr->flags |= RSPAMD_SYMBOL_GROUP_UNGROUPED;
index f9a79eef1d28b9213dbcf73e643af6bf395f021e..717aa81ce5ba25f79162bfdf9ef297ca631c563b 100644 (file)
@@ -3933,6 +3933,8 @@ lua_config_get_groups(lua_State *L)
                                lua_setfield(L, -2, "description");
                                lua_pushnumber(L, gr->max_score);
                                lua_setfield(L, -2, "max_score");
+                               lua_pushnumber(L, gr->min_score);
+                               lua_setfield(L, -2, "min_score");
                                lua_pushboolean(L, (gr->flags & RSPAMD_SYMBOL_GROUP_PUBLIC) != 0);
                                lua_setfield(L, -2, "is_public");
                                /* TODO: maybe push symbols as well */
index a035eeaae606f3a15df8d3a3e1571066c84cbb83..b92177f1be4eb17b6992d5a29860e7f049d48614 100644 (file)
@@ -2299,6 +2299,8 @@ fuzzy_insert_result(struct fuzzy_client_session *session,
         * Otherwise `value` means error code
         */
 
+       msg_debug_fuzzy_check("got reply with probability %.2f and value %.2f",
+                                                 (double) rep->v1.prob, (double) rep->v1.value);
        nval = fuzzy_normalize(rep->v1.value, weight);
 
        if (io) {
index 167b4c8911d0a9bf533ede6a147d90d630a50f15..456875cf2c5fab3fa543d3781b3dd5969069be07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 Vsevolod Stakhov
+ * Copyright 2024 Vsevolod Stakhov
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -444,6 +444,9 @@ rspamadm_configdump(int argc, char **argv, const struct rspamadm_command *cmd)
                                ucl_object_insert_key(gr_ucl,
                                                                          ucl_object_fromdouble(gr->max_score),
                                                                          "max_score", strlen("max_score"), false);
+                               ucl_object_insert_key(gr_ucl,
+                                                                         ucl_object_fromdouble(gr->min_score),
+                                                                         "min_score", strlen("min_score"), false);
                                ucl_object_insert_key(gr_ucl,
                                                                          ucl_object_fromstring(gr->description),
                                                                          "description", strlen("description"), false);