From fef5b856a497eb4e4b691d3596535073d61aadcc Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 24 Oct 2025 16:16:02 +0200 Subject: [PATCH] Regex: Prevent accidently copying the underlying `regex_t` Signed-off-by: Remi Gacogne --- pdns/misc.cc | 18 +++++++++++++++--- pdns/misc.hh | 30 ++++++++++++++++-------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/pdns/misc.cc b/pdns/misc.cc index 92921d3707..a280a91934 100644 --- a/pdns/misc.cc +++ b/pdns/misc.cc @@ -825,17 +825,29 @@ bool readFileIfThere(const char* fname, std::string* line) return stringfgets(filePtr.get(), *line); } -Regex::Regex(const string& expr) +Regex::Regex(const string& expr): + d_preg(new regex_t) { - if (auto ret = regcomp(&d_preg, expr.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED); ret != 0) { + if (auto ret = regcomp(d_preg.get(), expr.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED); ret != 0) { std::array errorBuffer{}; - if (regerror(ret, &d_preg, errorBuffer.data(), errorBuffer.size()) > 0) { + if (regerror(ret, d_preg.get(), errorBuffer.data(), errorBuffer.size()) > 0) { throw PDNSException("Regular expression " + expr + " did not compile: " + errorBuffer.data()); } throw PDNSException("Regular expression " + expr + " did not compile"); } } +/** call this to find out if 'line' matches your expression */ +bool Regex::match(const string &line) const +{ + return regexec(d_preg.get(), line.c_str(), 0, 0, 0) == 0; +} + +bool Regex::match(const DNSName& name) const +{ + return match(name.toStringNoDot()); +} + // if you end up here because valgrind told you were are doing something wrong // with msgh->msg_controllen, please refer to https://github.com/PowerDNS/pdns/pull/3962 // first. diff --git a/pdns/misc.hh b/pdns/misc.hh index 04b184f58c..b5deb14fa0 100644 --- a/pdns/misc.hh +++ b/pdns/misc.hh @@ -518,23 +518,25 @@ class Regex public: /** constructor that accepts the expression to regex */ Regex(const string &expr); - - ~Regex() - { - regfree(&d_preg); - } + Regex(const Regex&) = delete; + Regex& operator=(const Regex&) = delete; + Regex(Regex&& rhs) = default; + Regex& operator=(Regex&& rhs) = default; + ~Regex() = default; /** call this to find out if 'line' matches your expression */ - bool match(const string &line) const - { - return regexec(&d_preg,line.c_str(),0,0,0)==0; - } - bool match(const DNSName& name) const - { - return match(name.toStringNoDot()); - } + bool match(const string &line) const; + bool match(const DNSName& name) const; private: - regex_t d_preg; + struct Deleter + { + void operator()(regex_t* ptr) const noexcept { + regfree(ptr); + delete ptr; + } + }; + + std::unique_ptr d_preg; }; class SimpleMatch -- 2.47.3