]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Minor] maps: move glob pattern anchoring into rspamd_str_regexp_escape
authorVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 8 Jul 2026 09:09:41 +0000 (10:09 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 8 Jul 2026 09:09:41 +0000 (10:09 +0100)
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.

src/libserver/maps/map_helpers.c
src/libutil/str_util.c
src/libutil/str_util.h

index e0112feb9096a52d7f8bf1073dc745824b4d7fc1..aafde1d7e1a4c88dcbf39d5181ed8ed308ce2b51 100644 (file)
@@ -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 {
index fc78cd22dee2205f7b8d52bb4e64b26f03924b69..c884af20ebefd8550629bb9c73b7f4b9564e1d57 100644 (file)
@@ -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) {
index 8de4b361edaa2312d74ee785fc9093e84f13ab50..c28f6d6e1076648f430f69bc64b3e886a6842fd3 100644 (file)
@@ -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,
 };
 
 /**