]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Prevent infinite loop in fuzzy_check config transform
authorVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 12 Jan 2026 08:39:46 +0000 (08:39 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 12 Jan 2026 08:39:46 +0000 (08:39 +0000)
When transforming max_score -> hits_limit for backward compatibility,
directly assigning UCL object references between fields can corrupt
the internal linked list pointers (next/prev become self-referential).

This caused an infinite loop in ucl_object_lua_push_array() when the
C code tried to push the config object to Lua via LL_FOREACH macro.

Fix by using tonumber() to extract the numeric value instead of
copying the UCL object reference.

Reported-by: User via GDB backtrace showing hang at lua_ucl.c:240
Fixes: 7fd47dad2f9 ("[Feature] Rename fuzzy_check max_score to hits_limit for clarity")
lualib/lua_cfg_transform.lua

index 691f57f5cba910f19939859e526597b821e4fa14..f137dea30f3a5ae0bbb68f5a6ebe90fb90cd218f 100644 (file)
@@ -531,14 +531,16 @@ return function(cfg)
         -- max_score overrides hits_limit for backward compatibility
         -- This ensures local.d overrides using legacy max_score still work
         if rule.max_score then
-          rule.hits_limit = rule.max_score
+          -- Use tonumber() to extract the value, avoiding UCL object reference issues
+          -- that can cause circular linked list pointers and infinite loops
+          rule.hits_limit = tonumber(rule.max_score) or rule.max_score
           rule.max_score = nil
         end
         -- Also transform fuzzy_map entries
         if rule.fuzzy_map then
           for _, map_entry in pairs(rule.fuzzy_map) do
             if type(map_entry) == 'table' and map_entry.max_score then
-              map_entry.hits_limit = map_entry.max_score
+              map_entry.hits_limit = tonumber(map_entry.max_score) or map_entry.max_score
               map_entry.max_score = nil
             end
           end