From dbd475241cea95ac942cb58328da438a287e7c0f Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 20 Nov 2025 12:32:33 +0000 Subject: [PATCH] [Fix] Prevent infinite loop in split_networks_into_chunks() 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 | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/lualib/rspamadm/dns_tool.lua b/lualib/rspamadm/dns_tool.lua index cabc6aa75a..e6da7a251c 100644 --- a/lualib/rspamadm/dns_tool.lua +++ b/lualib/rspamadm/dns_tool.lua @@ -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 -- 2.47.3