]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Wrap DIR* objects in unique pointers to prevent memory leaks
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 29 Aug 2023 12:57:19 +0000 (14:57 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 10 Nov 2023 16:05:26 +0000 (17:05 +0100)
modules/geoipbackend/geoipbackend.cc
pdns/dnsbackend.cc
pdns/dnsdist-lua.cc
pdns/ixfrdist.cc
pdns/ixfrutils.cc
pdns/misc.cc

index 783c421e8307b2f95df6732777358fc974d59a79..681bf6d926407e6ec038d4d37f24a7f229fb18b4 100644 (file)
@@ -85,12 +85,12 @@ GeoIPBackend::GeoIPBackend(const string& suffix)
   WriteLock writeLock(&s_state_lock);
   setArgPrefix("geoip" + suffix);
   if (!getArg("dnssec-keydir").empty()) {
-    DIR* dir = opendir(getArg("dnssec-keydir").c_str());
-    if (dir == nullptr) {
+    auto dirHandle = std::unique_ptr<DIR, decltype(&closedir)>(opendir(getArg("dnssec-keydir").c_str()), closedir);
+    if (!dirHandle) {
       throw PDNSException("dnssec-keydir " + getArg("dnssec-keydir") + " does not exist");
     }
     d_dnssec = true;
-    closedir(dir);
+    dirHandle.reset();
   }
   if (s_rc == 0) { // first instance gets to open everything
     initialize();
index 8cceece2139077c83a0889cdc3693ba2c975bea4..71b05ff785971368e184b03c48df604fd3e8299e 100644 (file)
@@ -113,19 +113,18 @@ vector<string> BackendMakerClass::getModules()
 void BackendMakerClass::load_all()
 {
   // TODO: Implement this?
-  DIR *dir=opendir(arg()["module-dir"].c_str());
-  if(!dir) {
+  auto dir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(arg()["module-dir"].c_str()), closedir);
+  if (!dir) {
     g_log<<Logger::Error<<"Unable to open module directory '"<<arg()["module-dir"]<<"'"<<endl;
     return;
   }
-  struct dirent *entry;
-  while((entry=readdir(dir))) {
-    if(!strncmp(entry->d_name,"lib",3) &&
-       strlen(entry->d_name)>13 &&
-       !strcmp(entry->d_name+strlen(entry->d_name)-10,"backend.so"))
+  struct dirent* entry = nullptr;
+  while ((entry=readdir(dir.get()))) {
+    if (strncmp(entry->d_name, "lib", 3) == 0 &&
+       strlen(entry->d_name) > 13 &&
+       strcmp(entry->d_name + strlen(entry->d_name)-10, "backend.so") == 0)
       load(entry->d_name);
   }
-  closedir(dir);
 }
 
 void BackendMakerClass::load(const string &module)
index 78da52ec9a644976cb4b4a54019cf003caa16c0a..78490d756024e950397cd42d3877036c129e02f5 100644 (file)
@@ -1861,16 +1861,16 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
       return;
     }
 
-    DIR* dirp;
-    struct dirent* ent;
+    auto dirp = std::unique_ptr<DIR, decltype(&closedir)>(opendir(dirname.c_str()), closedir);
     std::vector<std::string> files;
-    if (!(dirp = opendir(dirname.c_str()))) {
+    if (!dirp) {
       errlog("Error opening the included directory %s!", dirname.c_str());
       g_outputBuffer = "Error opening the included directory " + dirname + "!";
       return;
     }
 
-    while ((ent = readdir(dirp)) != NULL) {
+    struct dirent* ent = nullptr;
+    while ((ent = readdir(dirp.get())) != NULL) {
       if (ent->d_name[0] == '.') {
         continue;
       }
@@ -1887,7 +1887,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
       }
     }
 
-    closedir(dirp);
+    dirp.reset();
     std::sort(files.begin(), files.end());
 
     g_included = true;
index 9a36a3c84b32e892e471634d170995472b732a53..7192cd9958b2583136422672d9636aeebe944223 100644 (file)
@@ -202,20 +202,19 @@ static bool sortSOA(uint32_t i, uint32_t j) {
 
 static void cleanUpDomain(const DNSName& domain, const uint16_t& keep, const string& workdir) {
   string dir = workdir + "/" + domain.toString();
-  DIR *dp;
-  dp = opendir(dir.c_str());
-  if (dp == nullptr) {
+  auto dirHandle = std::unique_ptr<DIR, decltype(&closedir)>(opendir(dir.c_str()), closedir);
+  if (!dirHandle) {
     return;
   }
   vector<uint32_t> zoneVersions;
-  struct dirent *d;
-  while ((d = readdir(dp)) != nullptr) {
-    if(!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {
+  struct dirent* entry = nullptr;
+  while ((entry = readdir(dirHandle.get())) != nullptr) {
+    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
       continue;
     }
-    zoneVersions.push_back(std::stoi(d->d_name));
+    zoneVersions.push_back(std::stoi(entry->d_name));
   }
-  closedir(dp);
+  dirHandle.reset();
   g_log<<Logger::Info<<"Found "<<zoneVersions.size()<<" versions of "<<domain<<", asked to keep "<<keep<<", ";
   if (zoneVersions.size() <= keep) {
     g_log<<Logger::Info<<"not cleaning up"<<endl;
index 4715e1dcd32769315a2502ac1cab1b866f051407..2c1031d8c7b8e710a88229c9c8ffb470fb113fe9 100644 (file)
@@ -75,18 +75,20 @@ uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, sh
 
 uint32_t getSerialFromDir(const std::string& dir)
 {
-  uint32_t ret=0;
-  DIR* dirhdl=opendir(dir.c_str());
-  if(!dirhdl)
+  uint32_t ret = 0;
+  auto dirhdl = std::unique_ptr<DIR, decltype(&closedir)>(opendir(dir.c_str()), closedir);
+  if (!dirhdl) {
     throw runtime_error("Could not open IXFR directory '" + dir + "': " + stringerror());
-  struct dirent *entry;
+  }
 
-  while((entry = readdir(dirhdl))) {
+  struct dirent* entry = nullptr;
+  while ((entry = readdir(dirhdl.get()))) {
     uint32_t num = atoi(entry->d_name);
-    if(std::to_string(num) == entry->d_name)
+    if (std::to_string(num) == entry->d_name) {
       ret = max(num, ret);
+    }
   }
-  closedir(dirhdl);
+
   return ret;
 }
 
index 4bbc865f6bed5f0d16d1bab96412442b2c4f1d1b..3cb1275d84547769172af0080e47926223ceb729 100644 (file)
@@ -1377,23 +1377,24 @@ DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum)
 uint64_t getOpenFileDescriptors(const std::string&)
 {
 #ifdef __linux__
-  DIR* dirhdl=opendir(("/proc/"+std::to_string(getpid())+"/fd/").c_str());
-  if(!dirhdl)
+  auto dirhdl = std::unique_ptr<DIR, decltype(&closedir)>(opendir(("/proc/"+std::to_string(getpid())+"/fd/").c_str()), closedir);
+  if (!dirhdl) {
     return 0;
+  }
 
-  struct dirent *entry;
-  int ret=0;
-  while((entry = readdir(dirhdl))) {
+  int ret = 0;
+  struct dirent* entry = nullptr;
+  while ((entry = readdir(dirhdl.get()))) {
     uint32_t num;
     try {
       pdns::checked_stoi_into(num, entry->d_name);
     } catch (...) {
       continue; // was not a number.
     }
-    if(std::to_string(num) == entry->d_name)
+    if (std::to_string(num) == entry->d_name) {
       ret++;
+    }
   }
-  closedir(dirhdl);
   return ret;
 
 #elif defined(__OpenBSD__)