]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Regex: Prevent accidently copying the underlying `regex_t`
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 24 Oct 2025 14:16:02 +0000 (16:16 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 24 Oct 2025 14:16:02 +0000 (16:16 +0200)
Signed-off-by: Remi Gacogne <remi.gacogne@powerdns.com>
pdns/misc.cc
pdns/misc.hh

index 92921d370769459b7a740602409e1a4faacd5647..a280a91934f28b53b7e096fc0a36e4b48bf54f64 100644 (file)
@@ -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<char, 1024> 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.
index 04b184f58cdf2324224ffe1d051dabacf021a2fe..b5deb14fa0321f43c778728cd07e13ac28283dc9 100644 (file)
@@ -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<regex_t, Deleter> d_preg;
 };
 
 class SimpleMatch