From: Vsevolod Stakhov Date: Wed, 8 Jul 2026 09:09:41 +0000 (+0100) Subject: [Minor] maps: move glob pattern anchoring into rspamd_str_regexp_escape X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38ffc00b25b37ac28afa10c6677c692ccbcc72ba;p=thirdparty%2Frspamd.git [Minor] maps: move glob pattern anchoring into rspamd_str_regexp_escape Add RSPAMD_REGEXP_ESCAPE_ANCHOR flag that wraps the escaped pattern into ^(?:...)$ within the same allocation instead of a second g_strdup_printf in the glob map insertion path. --- diff --git a/src/libserver/maps/map_helpers.c b/src/libserver/maps/map_helpers.c index e0112feb90..aafde1d7e1 100644 --- a/src/libserver/maps/map_helpers.c +++ b/src/libserver/maps/map_helpers.c @@ -685,14 +685,11 @@ void rspamd_map_helper_insert_re(gpointer st, gconstpointer key, gconstpointer v /* Check regexp stuff */ if (re_map->map_flags & RSPAMD_REGEXP_MAP_FLAG_GLOB) { - char *anchored; - - escaped = rspamd_str_regexp_escape(key, strlen(key), &escaped_len, - RSPAMD_REGEXP_ESCAPE_GLOB | RSPAMD_REGEXP_ESCAPE_UTF); /* Glob semantics: the pattern must match the subject as a whole */ - anchored = g_strdup_printf("^(?:%s)$", escaped); - re = rspamd_regexp_new(anchored, NULL, &err); - g_free(anchored); + escaped = rspamd_str_regexp_escape(key, strlen(key), &escaped_len, + RSPAMD_REGEXP_ESCAPE_GLOB | RSPAMD_REGEXP_ESCAPE_UTF | + RSPAMD_REGEXP_ESCAPE_ANCHOR); + re = rspamd_regexp_new(escaped, NULL, &err); g_free(escaped); } else { diff --git a/src/libutil/str_util.c b/src/libutil/str_util.c index fc78cd22de..c884af20eb 100644 --- a/src/libutil/str_util.c +++ b/src/libutil/str_util.c @@ -3515,6 +3515,11 @@ rspamd_str_regexp_escape(const char *pattern, gsize slen, } } + if (flags & RSPAMD_REGEXP_ESCAPE_ANCHOR) { + /* Room for ^(?: and )$ */ + len += 6; + } + if (flags & RSPAMD_REGEXP_ESCAPE_UTF) { if (rspamd_fast_utf8_validate(pattern, slen) != 0) { tmp_utf = rspamd_str_make_utf_valid(pattern, slen, NULL, NULL); @@ -3547,6 +3552,11 @@ rspamd_str_regexp_escape(const char *pattern, gsize slen, d = res; dend = d + len; + if (flags & RSPAMD_REGEXP_ESCAPE_ANCHOR) { + memcpy(d, "^(?:", 4); + d += 4; + } + while (p < end) { g_assert(d < dend); t = *p++; @@ -3646,6 +3656,11 @@ rspamd_str_regexp_escape(const char *pattern, gsize slen, *d++ = t; } + if (flags & RSPAMD_REGEXP_ESCAPE_ANCHOR) { + *d++ = ')'; + *d++ = '$'; + } + *d = '\0'; if (dst_len) { diff --git a/src/libutil/str_util.h b/src/libutil/str_util.h index 8de4b361ed..c28f6d6e10 100644 --- a/src/libutil/str_util.h +++ b/src/libutil/str_util.h @@ -505,6 +505,8 @@ enum rspamd_regexp_escape_flags { RSPAMD_REGEXP_ESCAPE_UTF = 1u << 0, RSPAMD_REGEXP_ESCAPE_GLOB = 1u << 1, RSPAMD_REGEXP_ESCAPE_RE = 1u << 2, + /* Wrap the result into ^(?:...)$ so it matches the subject as a whole */ + RSPAMD_REGEXP_ESCAPE_ANCHOR = 1u << 3, }; /**