From: Vsevolod Stakhov Date: Sat, 25 Apr 2026 19:03:05 +0000 (+0100) Subject: [Fix] fuzzy_check: handle NULL upstream in lua_ping_storage X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=191f8ae5a300edad5e3cf468e12c09db28aebf2b;p=thirdparty%2Frspamd.git [Fix] fuzzy_check: handle NULL upstream in lua_ping_storage fuzzy_lua_ping_storage selected an upstream from rule->read_servers without checking the result, then dereferenced the NULL pointer in rspamd_upstream_addr_next(). With the new deferred-DNS upstream layer this becomes reachable in normal operation (every upstream still pending), and was already reachable before whenever the alive list was empty. Audit of other rspamd_upstream_get / _forced / _except / _token_bucket call sites in C/C++ (rspamd_proxy.c, libserver/dns.c, fuzzy_backend_redis.c, http/http_connection.c, libstat http_backend, the other fuzzy_check sites) confirms they already guard the result with `if (up)` or a `while (up = ...)` loop; only this site was unchecked. Return (false, "no fuzzy storage upstream available for rule X") to the Lua caller instead of crashing. --- diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index 2d29a1431f..5c95ac6e7e 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -7163,6 +7163,12 @@ fuzzy_lua_ping_storage(lua_State *L) else { struct upstream *selected = rspamd_upstream_get(rule_found->read_servers, RSPAMD_UPSTREAM_ROUND_ROBIN, NULL, 0); + if (selected == NULL) { + lua_pushboolean(L, FALSE); + lua_pushfstring(L, "no fuzzy storage upstream available for rule %s", + rule_found->name); + return 2; + } addr = rspamd_upstream_addr_next(selected); }