From: Vsevolod Stakhov Date: Fri, 1 May 2026 08:03:55 +0000 (+0100) Subject: [Fix] upstream: bail out of get_random when only candidate is excluded X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df0165bee8e80c0273fbb96a73a6c21bd56968a2;p=thirdparty%2Frspamd.git [Fix] upstream: bail out of get_random when only candidate is excluded rspamd_upstream_get_random looped forever when alive->len == 1 and the single survivor matched the 'except' argument. Front-gate the empty and single-survivor cases explicitly; the unbounded loop only runs for n >= 2 where it is guaranteed to terminate. --- diff --git a/src/libutil/upstream.c b/src/libutil/upstream.c index a341407c29..9aa0dd7f6a 100644 --- a/src/libutil/upstream.c +++ b/src/libutil/upstream.c @@ -2008,13 +2008,23 @@ static struct upstream * rspamd_upstream_get_random(struct upstream_list *ups, struct upstream *except) { - for (;;) { - unsigned int idx = ottery_rand_range(ups->alive->len - 1); - struct upstream *up; + unsigned int n = ups->alive->len; + struct upstream *up; + + if (n == 0) { + return NULL; + } + if (n == 1) { + up = g_ptr_array_index(ups->alive, 0); + return (except != NULL && up == except) ? NULL : up; + } + /* n >= 2: at most one excluded, retry-on-collision is bounded */ + for (;;) { + unsigned int idx = ottery_rand_range(n - 1); up = g_ptr_array_index(ups->alive, idx); - if (except && up == except) { + if (except != NULL && up == except) { continue; }