]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Prevent infinite loop in split_networks_into_chunks() 5757/head
authorVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 20 Nov 2025 12:32:33 +0000 (12:32 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 20 Nov 2025 12:32:33 +0000 (12:32 +0000)
If a single IP network entry exceeds max_record_length (450 chars) on its own,
the code would enter an infinite loop. Added validation to check if individual
items can fit before attempting to add them to chunks. Items that are too large
are now skipped with a warning message.

lualib/rspamadm/dns_tool.lua

index cabc6aa75a9719390237e936f72a1a0f85b9b7e4..e6da7a251c2aa5f422f02f5b9f201500d25e8c94 100644 (file)
@@ -385,22 +385,32 @@ local function spf_flatten_handler(opts)
     end
 
     for _, item in ipairs(all_v4) do
-      table.insert(current_chunk_v4, item)
-      local test_record = build_spf_record(current_chunk_v4, current_chunk_v6, {}, all_mechs, nil)
-      if #test_record > max_record_length then
-        table.remove(current_chunk_v4)
-        finalize_chunk()
+      local single_item_test = build_spf_record({item}, {}, {}, all_mechs, nil)
+      if #single_item_test > max_record_length then
+        printf('Warning: IPv4 network %s is too large to fit in a single SPF record, skipping', item.net)
+      else
         table.insert(current_chunk_v4, item)
+        local test_record = build_spf_record(current_chunk_v4, current_chunk_v6, {}, all_mechs, nil)
+        if #test_record > max_record_length then
+          table.remove(current_chunk_v4)
+          finalize_chunk()
+          table.insert(current_chunk_v4, item)
+        end
       end
     end
 
     for _, item in ipairs(all_v6) do
-      table.insert(current_chunk_v6, item)
-      local test_record = build_spf_record(current_chunk_v4, current_chunk_v6, {}, all_mechs, nil)
-      if #test_record > max_record_length then
-        table.remove(current_chunk_v6)
-        finalize_chunk()
+      local single_item_test = build_spf_record({}, {item}, {}, all_mechs, nil)
+      if #single_item_test > max_record_length then
+        printf('Warning: IPv6 network %s is too large to fit in a single SPF record, skipping', item.net)
+      else
         table.insert(current_chunk_v6, item)
+        local test_record = build_spf_record(current_chunk_v4, current_chunk_v6, {}, all_mechs, nil)
+        if #test_record > max_record_length then
+          table.remove(current_chunk_v6)
+          finalize_chunk()
+          table.insert(current_chunk_v6, item)
+        end
       end
     end