From: Vsevolod Stakhov Date: Fri, 16 Jul 2021 11:24:29 +0000 (+0100) Subject: [Fix] Fix storing of the regexps inside variant X-Git-Tag: 3.0~147 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8c9abcc404977124f44058c7738546f7ea2fc500;p=thirdparty%2Frspamd.git [Fix] Fix storing of the regexps inside variant --- diff --git a/src/libserver/composites/composites.cxx b/src/libserver/composites/composites.cxx index 17e8d7575d..7778f854a9 100644 --- a/src/libserver/composites/composites.cxx +++ b/src/libserver/composites/composites.cxx @@ -93,33 +93,56 @@ struct composites_data { }; struct rspamd_composite_option_match { - std::variant match; + struct rspamd_regexp_wrapper { + explicit rspamd_regexp_wrapper(rspamd_regexp_t *re) noexcept : re(rspamd_regexp_ref(re)) {} + ~rspamd_regexp_wrapper() { + if (re) { + rspamd_regexp_unref(re); + } + } + rspamd_regexp_wrapper(const rspamd_regexp_wrapper &other) { + re = rspamd_regexp_ref(other.re); + } + rspamd_regexp_wrapper(rspamd_regexp_wrapper &&other) { + std::swap(re, other.re); + } + const rspamd_regexp_wrapper & operator= (const rspamd_regexp_wrapper &other) noexcept { + if (re) { + rspamd_regexp_unref(re); + } + re = rspamd_regexp_ref(other.re); + return *this; + } + const rspamd_regexp_wrapper & operator= (rspamd_regexp_wrapper &&other) noexcept { + std::swap(re, other.re); + return *this; + } + rspamd_regexp_wrapper() = default; + rspamd_regexp_t *re = nullptr; + }; + + std::variant match; - explicit rspamd_composite_option_match(const char *start, std::size_t len) + explicit rspamd_composite_option_match(const char *start, std::size_t len) noexcept { match = std::string_view{start, len}; } - explicit rspamd_composite_option_match(rspamd_regexp_t *re) + explicit rspamd_composite_option_match(rspamd_regexp_t *re) noexcept { - match = re; + match = rspamd_regexp_wrapper(re); } - ~rspamd_composite_option_match() - { - if (std::holds_alternative(match)) { - rspamd_regexp_unref(std::get(match)); - } - } + ~rspamd_composite_option_match() = default; - auto math_opt(const std::string_view &data) const -> bool + auto match_opt(const std::string_view &data) const -> bool { return std::visit([&](auto arg) -> bool { if constexpr (std::is_same_v) { return data == arg; } else { - return rspamd_regexp_search(arg, + return rspamd_regexp_search(arg.re, data.data(), data.size(), nullptr, nullptr, false, nullptr); } @@ -133,7 +156,7 @@ struct rspamd_composite_option_match { return std::string_view(arg); } else { - return std::string_view(rspamd_regexp_get_pattern(arg)); + return std::string_view(rspamd_regexp_get_pattern(arg.re)); } }, match); } @@ -381,6 +404,7 @@ rspamd_composite_expr_parse(const gchar *line, gsize len, } else { atom->opts.emplace_back(re); + rspamd_regexp_unref(re); } if (*p == ',') { @@ -573,7 +597,7 @@ process_single_symbol(struct composites_data *cd, auto found = false; DL_FOREACH (ms->opts_head, opt) { - if (cur_opt.math_opt({opt->option, opt->optlen})) { + if (cur_opt.match_opt({opt->option, opt->optlen})) { found = true; break; }