[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1108915: marked as done (unblock: pdns/4.9.7-1 [pre-approval])



Your message dated Tue, 08 Jul 2025 17:02:43 +0000
with message-id <E1uZBiN-00C60t-2e@respighi.debian.org>
and subject line unblock pdns
has caused the Debian Bug report #1108915,
regarding unblock: pdns/4.9.7-1 [pre-approval]
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1108915: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1108915
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
X-Debbugs-Cc: pdns@packages.debian.org
Control: affects -1 + src:pdns
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package pdns

pdns 4.9.7 is an upstream bugfix release in the 4.9 series.
Previously we had 4.9.4; upstream released 4.9.5 (after the freeze 
started) and 4.9.7 (today) - 4.9.6 was skipped.

I'd like to take the latest upstream release into unstable and 
testing. Have not uploaded it yet.

[ Reason ]
Accepting the upstream bugfix release will hopefully make applying 
future security fixes easier, or we can just use a future bugfix 
release for them.

4.9.5 includes the patch we applied to 4.9.4 to fix tests on s390x.

[ Impact ]
If we stay on 4.9.4, the diff for security fixes will be larger and 
thus harder.
We'll also miss out on upstream bug- and performance-fixes to the LMDB
backend, better exception handling in Lua functions leading to 
SERVFAILs, an interop fix for TSIG and a compile fix for newer gcc.

[ Tests ]
In Debian we only have smoke tests, however they did find the s390x 
mysql issue in the past. Upstream has a big test suite they run for 
releases.

[ Risks ]
Not sure. The diff seems right to me for the fixes upstream 
described.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Other info ]

The attached debdiff was produced using:
  debdiff pdns_4.9.4-2.dsc pdns_4.9.7-1.dsc | filterdiff -x '*.1' > pdns_4.9.7-1.filtered.debdiff
to exclude the date changes to the xxx.1 manpages.

unblock pdns/4.9.7-1
diff -Nru pdns-4.9.4/configure pdns-4.9.7/configure
--- pdns-4.9.4/configure	2025-02-06 16:18:00.000000000 +0100
+++ pdns-4.9.7/configure	2025-07-07 09:42:38.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for pdns 4.9.4.
+# Generated by GNU Autoconf 2.71 for pdns 4.9.7.
 #
 #
 # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
@@ -618,8 +618,8 @@
 # Identity of this package.
 PACKAGE_NAME='pdns'
 PACKAGE_TARNAME='pdns'
-PACKAGE_VERSION='4.9.4'
-PACKAGE_STRING='pdns 4.9.4'
+PACKAGE_VERSION='4.9.7'
+PACKAGE_STRING='pdns 4.9.7'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1698,7 +1698,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures pdns 4.9.4 to adapt to many kinds of systems.
+\`configure' configures pdns 4.9.7 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1769,7 +1769,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of pdns 4.9.4:";;
+     short | recursive ) echo "Configuration of pdns 4.9.7:";;
    esac
   cat <<\_ACEOF
 
@@ -2040,7 +2040,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-pdns configure 4.9.4
+pdns configure 4.9.7
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2529,7 +2529,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by pdns $as_me 4.9.4, which was
+It was created by pdns $as_me 4.9.7, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -4027,7 +4027,7 @@
 
 # Define the identity of the package.
  PACKAGE='pdns'
- VERSION='4.9.4'
+ VERSION='4.9.7'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -32467,7 +32467,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by pdns $as_me 4.9.4, which was
+This file was extended by pdns $as_me 4.9.7, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -32535,7 +32535,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-pdns config.status 4.9.4
+pdns config.status 4.9.7
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
diff -Nru pdns-4.9.4/configure.ac pdns-4.9.7/configure.ac
--- pdns-4.9.4/configure.ac	2025-02-06 16:17:52.000000000 +0100
+++ pdns-4.9.7/configure.ac	2025-07-07 09:42:29.000000000 +0200
@@ -1,6 +1,6 @@
 AC_PREREQ([2.69])
 
-AC_INIT([pdns], [4.9.4])
+AC_INIT([pdns], [4.9.7])
 AC_CONFIG_AUX_DIR([build-aux])
 AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip tar-ustar -Wno-portability subdir-objects parallel-tests 1.11])
 AM_SILENT_RULES([yes])
diff -Nru pdns-4.9.4/debian/changelog pdns-4.9.7/debian/changelog
--- pdns-4.9.4/debian/changelog	2025-03-21 13:09:53.000000000 +0100
+++ pdns-4.9.7/debian/changelog	2025-07-07 12:15:52.000000000 +0200
@@ -1,3 +1,10 @@
+pdns (4.9.7-1) unstable; urgency=medium
+
+  * New upstream version 4.9.7
+  * Drop upstream-applied patch
+
+ -- Chris Hofstaedtler <zeha@debian.org>  Mon, 07 Jul 2025 12:15:52 +0200
+
 pdns (4.9.4-2) unstable; urgency=medium
 
   * Add upstream-pending patch to fix mysqlbackend on s390x
diff -Nru pdns-4.9.4/debian/patches/series pdns-4.9.7/debian/patches/series
--- pdns-4.9.4/debian/patches/series	2025-03-21 13:09:34.000000000 +0100
+++ pdns-4.9.7/debian/patches/series	2025-07-07 12:15:39.000000000 +0200
@@ -1 +0,0 @@
-upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch
diff -Nru pdns-4.9.4/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch pdns-4.9.7/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch
--- pdns-4.9.4/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch	2025-03-21 13:09:34.000000000 +0100
+++ pdns-4.9.7/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,43 +0,0 @@
-From: Chris Hofstaedtler <chris.hofstaedtler@deduktiva.com>
-Date: Fri, 21 Mar 2025 12:54:21 +0100
-Subject: mysql: use MYSQL_TYPE_LONGLONG on 64bit platforms
-
-Found on s390x.
-
-https://github.com/PowerDNS/pdns/pull/15340/
----
- modules/gmysqlbackend/smysql.cc | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
-
-diff --git a/modules/gmysqlbackend/smysql.cc b/modules/gmysqlbackend/smysql.cc
-index efcbffd..4cc7856 100644
---- a/modules/gmysqlbackend/smysql.cc
-+++ b/modules/gmysqlbackend/smysql.cc
-@@ -116,7 +116,12 @@ public:
-       releaseStatement();
-       throw SSqlException("Attempt to bind more parameters than query has: " + d_query);
-     }
--    d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG;
-+    if constexpr (sizeof(long) == 4) {
-+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG;
-+    }
-+    else {
-+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG;
-+    }
-     d_req_bind[d_paridx].buffer = new long[1];
-     *((long*)d_req_bind[d_paridx].buffer) = value;
-     d_paridx++;
-@@ -129,7 +134,12 @@ public:
-       releaseStatement();
-       throw SSqlException("Attempt to bind more parameters than query has: " + d_query);
-     }
--    d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG;
-+    if constexpr (sizeof(long) == 4) {
-+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG;
-+    }
-+    else {
-+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG;
-+    }
-     d_req_bind[d_paridx].buffer = new unsigned long[1];
-     d_req_bind[d_paridx].is_unsigned = 1;
-     *((unsigned long*)d_req_bind[d_paridx].buffer) = value;
diff -Nru pdns-4.9.4/docs/ixfrdist.yml.5 pdns-4.9.7/docs/ixfrdist.yml.5
--- pdns-4.9.4/docs/ixfrdist.yml.5	2025-02-06 16:19:08.000000000 +0100
+++ pdns-4.9.7/docs/ixfrdist.yml.5	2025-07-07 09:43:48.000000000 +0200
@@ -27,7 +27,7 @@
 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
 ..
-.TH "IXFRDIST.YML" "5" "Feb 06, 2025" "" "PowerDNS Authoritative Server"
+.TH "IXFRDIST.YML" "5" "Jul 07, 2025" "" "PowerDNS Authoritative Server"
 .SH NAME
 ixfrdist.yml \- The ixfrdist configuration file
 .SH SYNOPSIS
diff -Nru pdns-4.9.4/ext/lmdb-safe/lmdb-safe.hh pdns-4.9.7/ext/lmdb-safe/lmdb-safe.hh
--- pdns-4.9.4/ext/lmdb-safe/lmdb-safe.hh	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/ext/lmdb-safe/lmdb-safe.hh	2025-07-07 09:42:15.000000000 +0200
@@ -12,6 +12,8 @@
 #include <mutex>
 #include <vector>
 #include <algorithm>
+#include <string>
+#include <string_view>
 
 #include "config.h"
 
@@ -24,6 +26,13 @@
 #endif
 
 using std::string_view;
+using std::string;
+
+#if BOOST_VERSION >= 106100
+#define StringView string_view
+#else
+#define StringView string
+#endif
 
 /* open issues:
  *
@@ -98,7 +107,7 @@
   std::map<std::thread::id, int> d_ROtransactionsOut;
 };
 
-std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB=(sizeof(void *)==4) ? 100 : 16000);
+std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB);
 
 #ifndef DNSDIST
 
@@ -300,6 +309,9 @@
     return ret;
   }
 
+  template <class T>
+  T get() const;
+
   operator MDB_val&()
   {
     return d_mdbval;
@@ -312,6 +324,12 @@
 #endif
 };
 
+template <>
+inline std::string MDBInVal::get<std::string>() const
+{
+  return {static_cast<char*>(d_mdbval.mv_data), d_mdbval.mv_size};
+}
+
 class MDBROCursor;
 
 class MDBROTransactionImpl
@@ -415,6 +433,7 @@
 private:
   std::vector<T*> *d_registry;
   MDB_cursor* d_cursor{nullptr};
+  std::string d_prefix{""};
 public:
   MDB_txn* d_txn{nullptr}; // ew, public
   uint64_t d_txtime{0};
@@ -523,6 +542,9 @@
 
     while (true) {
       auto sval = data.getNoStripHeader<std::string_view>();
+      if (d_prefix.length() > 0 && key.getNoStripHeader<StringView>().rfind(d_prefix, 0) != 0) {
+        return MDB_NOTFOUND;
+      }
 
       if (!LMDBLS::LSisDeleted(sval)) {
         // done!
@@ -573,6 +595,7 @@
 public:
   int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op)
   {
+    d_prefix.clear();
     int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op);
     if(rc && rc != MDB_NOTFOUND)
        throw std::runtime_error("Unable to get from cursor: " + std::string(mdb_strerror(rc)));
@@ -581,6 +604,7 @@
 
   int find(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
   {
+    d_prefix.clear();
     key.d_mdbval = in.d_mdbval;
     int rc=mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET);
     if(rc && rc != MDB_NOTFOUND)
@@ -588,8 +612,20 @@
     return skipDeleted(key, data, MDB_SET, rc);
   }
 
+  int prefix(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
+  {
+    d_prefix = in.get<string>();
+    return _lower_bound(in, key, data);
+  }
+
   int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
   {
+    d_prefix.clear();
+    return _lower_bound(in, key, data);
+  }
+
+  int _lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) // used by prefix() and lower_bound()
+  {
     key.d_mdbval = in.d_mdbval;
 
     int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET_RANGE);
diff -Nru pdns-4.9.4/ext/lmdb-safe/lmdb-typed.hh pdns-4.9.7/ext/lmdb-safe/lmdb-typed.hh
--- pdns-4.9.4/ext/lmdb-safe/lmdb-typed.hh	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/ext/lmdb-safe/lmdb-typed.hh	2025-07-07 09:42:15.000000000 +0200
@@ -284,14 +284,19 @@
     // }
 
     //! Get item with id, from main table directly
-    bool get(uint32_t id, T& t)
+    int get2(uint32_t itemId, T& value)
     {
-      MDBOutVal data;
-      if((*d_parent.d_txn)->get(d_parent.d_parent->d_main, id, data))
-        return false;
-
-      serFromString(data.get<std::string>(), t);
-      return true;
+      MDBOutVal data{};
+      int rc;
+      rc = (*d_parent.d_txn)->get(d_parent.d_parent->d_main, itemId, data);
+      if (rc == 0) {
+        serFromString(data.get<std::string>(), value);
+      }
+      return rc;
+    }
+    bool get(uint32_t itemId, T& value)
+    {
+      return get2(itemId, value) == 0;
     }
 
     //! Get item through index N, then via the main database
@@ -309,17 +314,24 @@
       // because we know we only want one item, pass onlyOldest=true to consistently get the same one out of a set of duplicates
       get_multi<N>(key, ids, true);
 
-      if (ids.size() == 0) {
+      switch (ids.size()) {
+      case 0:
         return 0;
-      }
-
-      if (ids.size() == 1) {
-        if (get(ids[0], out)) {
+      case 1: {
+        auto rc = get2(ids[0], out);
+        if (rc == 0) {
           return ids[0];
         }
+        if (rc == MDB_NOTFOUND) {
+          /* element not present, or has been marked deleted */
+          return 0;
+        }
+        throw std::runtime_error("in index get, failed (" + std::to_string(rc) + ")");
+        break;
+      }
+      default:
+        throw std::runtime_error("in index get, found more than one item");
       }
-
-      throw std::runtime_error("in index get, found more than one item");
     }
 
     // //! Cardinality of index N
diff -Nru pdns-4.9.4/modules/gmysqlbackend/smysql.cc pdns-4.9.7/modules/gmysqlbackend/smysql.cc
--- pdns-4.9.4/modules/gmysqlbackend/smysql.cc	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/modules/gmysqlbackend/smysql.cc	2025-07-07 09:42:15.000000000 +0200
@@ -116,7 +116,12 @@
       releaseStatement();
       throw SSqlException("Attempt to bind more parameters than query has: " + d_query);
     }
-    d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG;
+    if constexpr (sizeof(long) == 4) {
+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+    }
+    else {
+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+    }
     d_req_bind[d_paridx].buffer = new long[1];
     *((long*)d_req_bind[d_paridx].buffer) = value;
     d_paridx++;
@@ -129,7 +134,12 @@
       releaseStatement();
       throw SSqlException("Attempt to bind more parameters than query has: " + d_query);
     }
-    d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG;
+    if constexpr (sizeof(long) == 4) {
+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+    }
+    else {
+      d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
+    }
     d_req_bind[d_paridx].buffer = new unsigned long[1];
     d_req_bind[d_paridx].is_unsigned = 1;
     *((unsigned long*)d_req_bind[d_paridx].buffer) = value;
diff -Nru pdns-4.9.4/modules/lmdbbackend/lmdbbackend.cc pdns-4.9.7/modules/lmdbbackend/lmdbbackend.cc
--- pdns-4.9.4/modules/lmdbbackend/lmdbbackend.cc	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/modules/lmdbbackend/lmdbbackend.cc	2025-07-07 09:42:15.000000000 +0200
@@ -656,8 +656,6 @@
 
   string syncMode = toLower(getArg("sync-mode"));
 
-  d_random_ids = mustDo("random-ids");
-
   if (syncMode == "nosync")
     d_asyncFlag = MDB_NOSYNC;
   else if (syncMode == "nometasync")
@@ -667,17 +665,14 @@
   else
     throw std::runtime_error("Unknown sync mode " + syncMode + " requested for LMDB backend");
 
-  uint64_t mapSize = 0;
+  d_mapsize = 0;
   try {
-    mapSize = std::stoll(getArg("map-size"));
+    d_mapsize = std::stoll(getArg("map-size"));
   }
   catch (const std::exception& e) {
     throw std::runtime_error(std::string("Unable to parse the 'map-size' LMDB value: ") + e.what());
   }
 
-  LMDBLS::s_flag_deleted = mustDo("flag-deleted");
-  d_handle_dups = false;
-
   if (mustDo("lightning-stream")) {
     d_random_ids = true;
     d_handle_dups = true;
@@ -687,6 +682,11 @@
       throw std::runtime_error(std::string("running with Lightning Stream support requires shards=1"));
     }
   }
+  else {
+    d_random_ids = mustDo("random-ids");
+    d_handle_dups = false;
+    LMDBLS::s_flag_deleted = mustDo("flag-deleted");
+  }
 
   bool opened = false;
 
@@ -723,7 +723,7 @@
         throw std::runtime_error("Somehow, we are not at schema version 5. Giving up");
       }
 
-      d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains_v5");
+      d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize), "domains_v5");
       d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata_v5");
       d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata_v5");
       d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig_v5");
@@ -770,7 +770,7 @@
   }
 
   if (!opened) {
-    d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains_v5");
+    d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize), "domains_v5");
     d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata_v5");
     d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata_v5");
     d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig_v5");
@@ -1211,7 +1211,7 @@
   auto& shard = d_trecords[id % s_shards];
   if (!shard.env) {
     shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(),
-                          MDB_NOSUBDIR | d_asyncFlag, 0600);
+                          MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize);
     shard.dbi = shard.env->openDB("records_v5", MDB_CREATE);
   }
   auto ret = std::make_shared<RecordsRWTransaction>(shard.env->getRWTransaction());
@@ -1228,7 +1228,7 @@
       throw DBException("attempting to start nested transaction without open parent env");
     }
     shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(),
-                          MDB_NOSUBDIR | d_asyncFlag, 0600);
+                          MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize);
     shard.dbi = shard.env->openDB("records_v5", MDB_CREATE);
   }
 
@@ -1405,10 +1405,7 @@
   d_matchkey = co(di.id);
 
   MDBOutVal key, val;
-  auto a = d_getcursor->lower_bound(d_matchkey, key, val);
-  auto b0 = key.getNoStripHeader<StringView>();
-  auto b = b0.rfind(d_matchkey, 0);
-  if (a || b != 0) {
+  if (d_getcursor->prefix(d_matchkey, key, val) != 0) {
     d_getcursor.reset();
   }
 
@@ -1470,7 +1467,7 @@
     d_matchkey = co(zoneId, relqname, type.getCode());
   }
 
-  if (d_getcursor->lower_bound(d_matchkey, key, val) || key.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+  if (d_getcursor->prefix(d_matchkey, key, val) != 0) {
     d_getcursor.reset();
     if (d_dolog) {
       g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us to execute (found nothing)" << endl;
@@ -1508,7 +1505,7 @@
 
       if (zr.dr.d_type == QType::NSEC3) {
         // Hit a magic NSEC3 skipping
-        if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+        if (d_getcursor->next(d_currentKey, d_currentVal) != 0) {
           // cerr<<"resetting d_getcursor 1"<<endl;
           d_getcursor.reset();
         }
@@ -1536,7 +1533,7 @@
 
       if (d_currentrrsetpos >= d_currentrrset.size()) {
         d_currentrrset.clear(); // will invalidate lrr
-        if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+        if (d_getcursor->next(d_currentKey, d_currentVal) != 0) {
           // cerr<<"resetting d_getcursor 2"<<endl;
           d_getcursor.reset();
         }
@@ -2423,7 +2420,7 @@
 
   auto cursor = txn->txn->getCursor(txn->db->dbi);
   MDBOutVal key, val;
-  if (cursor.lower_bound(matchkey, key, val)) {
+  if (cursor.prefix(matchkey, key, val) != 0) {
     // cout << "Could not find anything"<<endl;
     return false;
   }
@@ -2431,7 +2428,7 @@
   bool hasOrderName = !ordername.empty();
   bool needNSEC3 = hasOrderName;
 
-  for (; key.getNoStripHeader<StringView>().rfind(matchkey, 0) == 0;) {
+  do {
     vector<LMDBResourceRecord> lrrs;
 
     if (co.getQType(key.getNoStripHeader<StringView>()) != QType::NSEC3) {
@@ -2456,9 +2453,7 @@
       }
     }
 
-    if (cursor.next(key, val))
-      break;
-  }
+  } while (cursor.next(key, val) == 0);
 
   bool del = false;
   LMDBResourceRecord lrr;
diff -Nru pdns-4.9.4/modules/lmdbbackend/lmdbbackend.hh pdns-4.9.7/modules/lmdbbackend/lmdbbackend.hh
--- pdns-4.9.4/modules/lmdbbackend/lmdbbackend.hh	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/modules/lmdbbackend/lmdbbackend.hh	2025-07-07 09:42:15.000000000 +0200
@@ -333,4 +333,5 @@
   bool d_random_ids;
   bool d_handle_dups;
   DTime d_dtime; // used only for logging
+  uint64_t d_mapsize;
 };
diff -Nru pdns-4.9.4/pdns/credentials.hh pdns-4.9.7/pdns/credentials.hh
--- pdns-4.9.4/pdns/credentials.hh	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/pdns/credentials.hh	2025-07-07 09:42:15.000000000 +0200
@@ -21,7 +21,7 @@
  */
 #pragma once
 
-#include <memory>
+#include <cstdint>
 #include <string>
 
 class SensitiveData
diff -Nru pdns-4.9.4/pdns/dnssecinfra.cc pdns-4.9.7/pdns/dnssecinfra.cc
--- pdns-4.9.4/pdns/dnssecinfra.cc	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/pdns/dnssecinfra.cc	2025-07-07 09:42:15.000000000 +0200
@@ -782,7 +782,7 @@
   DNSPacketWriter dw(signVect, DNSName(), 0);
   auto pos=signVect.size();
   if(!timersonly) {
-    dw.xfrName(tsigKeyName, false);
+    dw.xfrName(tsigKeyName.makeLowerCase(), false);
     dw.xfr16BitInt(QClass::ANY); // class
     dw.xfr32BitInt(0);    // TTL
     dw.xfrName(trc.d_algoName.makeLowerCase(), false);
diff -Nru pdns-4.9.4/pdns/lua-record.cc pdns-4.9.7/pdns/lua-record.cc
--- pdns-4.9.4/pdns/lua-record.cc	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/pdns/lua-record.cc	2025-07-07 09:42:15.000000000 +0200
@@ -915,81 +915,87 @@
       return std::string("error");
     });
   lua.writeFunction("createForward", []() {
-      static string allZerosIP("0.0.0.0");
-      DNSName rel=s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone);
-      // parts is something like ["1", "2", "3", "4", "static"] or
-      // ["1", "2", "3", "4"] or ["ip40414243", "ip-addresses", ...]
-      auto parts = rel.getRawLabels();
-      // Yes, this still breaks if an 1-2-3-4.XXXX is nested too deeply...
-      if(parts.size()>=4) {
-        try {
-          ComboAddress ca(parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3]);
-          return ca.toString();
-        } catch (const PDNSException &e) {
-          return allZerosIP;
-        }
-      } else if (!parts.empty()) {
-        auto& input = parts.at(0);
-
-        // allow a word without - in front, as long as it does not contain anything that could be a number
-        size_t nonhexprefix = strcspn(input.c_str(), "0123456789abcdefABCDEF");
-        if (nonhexprefix > 0) {
-          input = input.substr(nonhexprefix);
-        }
-
-        // either hex string, or 12-13-14-15
-        vector<string> ip_parts;
-
-        stringtok(ip_parts, input, "-");
-        unsigned int x1, x2, x3, x4;
-        if (ip_parts.size() >= 4) {
-          // 1-2-3-4 with any prefix (e.g. ip-foo-bar-1-2-3-4)
-          string ret;
-          for (size_t index=4; index > 0; index--) {
-            auto octet = ip_parts[ip_parts.size() - index];
-            try {
-              auto octetVal = std::stol(octet);
+      static string allZerosIP{"0.0.0.0"};
+      try {
+        DNSName rel{s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone)};
+
+        // parts is something like ["1", "2", "3", "4", "static"] or
+        // ["1", "2", "3", "4"] or ["ip40414243", "ip-addresses", ...]
+        auto parts = rel.getRawLabels();
+        // Yes, this still breaks if an 1-2-3-4.XXXX is nested too deeply...
+        if (parts.size() >= 4) {
+          ComboAddress address(parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3]);
+          return address.toString();
+        }
+	if (!parts.empty()) {
+          auto& input = parts.at(0);
+
+          // allow a word without - in front, as long as it does not contain anything that could be a number
+          size_t nonhexprefix = strcspn(input.c_str(), "0123456789abcdefABCDEF");
+          if (nonhexprefix > 0) {
+            input = input.substr(nonhexprefix);
+          }
+
+          // either hex string, or 12-13-14-15
+          vector<string> ip_parts;
+
+          stringtok(ip_parts, input, "-");
+          if (ip_parts.size() >= 4) {
+            // 1-2-3-4 with any prefix (e.g. ip-foo-bar-1-2-3-4)
+            string ret;
+            for (size_t index=4; index > 0; index--) {
+              auto octet = ip_parts.at(ip_parts.size() - index);
+              auto octetVal = std::stol(octet); // may throw
               if (octetVal >= 0 && octetVal <= 255) {
-                ret += ip_parts.at(ip_parts.size() - index) + ".";
+                ret += octet + ".";
               } else {
                 return allZerosIP;
               }
-            } catch (const std::exception &e) {
-              return allZerosIP;
             }
+            ret.resize(ret.size() - 1); // remove trailing dot after last octet
+            return ret;
           }
-          ret.resize(ret.size() - 1); // remove trailing dot after last octet
-          return ret;
-        }
-        if(input.length() >= 8) {
-          auto last8 = input.substr(input.length()-8);
-          if(sscanf(last8.c_str(), "%02x%02x%02x%02x", &x1, &x2, &x3, &x4)==4) {
-            return std::to_string(x1) + "." + std::to_string(x2) + "." + std::to_string(x3) + "." + std::to_string(x4);
+          if (input.length() >= 8) {
+            auto last8 = input.substr(input.length()-8);
+            unsigned int part1{0};
+            unsigned int part2{0};
+            unsigned int part3{0};
+            unsigned int part4{0};
+            if (sscanf(last8.c_str(), "%02x%02x%02x%02x", &part1, &part2, &part3, &part4) == 4) {
+              ComboAddress address(std::to_string(part1) + "." + std::to_string(part2) + "." + std::to_string(part3) + "." + std::to_string(part4));
+              return address.toString();
+            }
           }
         }
+        return allZerosIP;
+      } catch (const PDNSException &e) {
+        return allZerosIP;
       }
-      return allZerosIP;
     });
 
   lua.writeFunction("createForward6", []() {
-      DNSName rel=s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone);
-      auto parts = rel.getRawLabels();
-      if(parts.size()==8) {
-        string tot;
-        for(int i=0; i<8; ++i) {
-          if(i)
-            tot.append(1,':');
-          tot+=parts[i];
+      static string allZerosIP{"::"};
+      try {
+        DNSName rel{s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone)};
+
+        auto parts = rel.getRawLabels();
+        if (parts.size() == 8) {
+          string tot;
+          for (int chunk = 0; chunk < 8; ++chunk) {
+            if (chunk != 0) {
+              tot.append(1, ':');
+	      }
+            tot += parts.at(chunk);
+          }
+          ComboAddress address(tot);
+          return address.toString();
         }
-        ComboAddress ca(tot);
-        return ca.toString();
-      }
-      else if(parts.size()==1) {
-        if (parts[0].find('-') != std::string::npos) {
-          boost::replace_all(parts[0],"-",":");
-          ComboAddress ca(parts[0]);
-          return ca.toString();
-        } else {
+        if (parts.size() == 1) {
+          if (parts[0].find('-') != std::string::npos) {
+            std::replace(parts[0].begin(), parts[0].end(), '-', ':');
+            ComboAddress address(parts[0]);
+            return address.toString();
+          }
           if (parts[0].size() >= 32) {
             auto ippart = parts[0].substr(parts[0].size()-32);
             auto fulladdress =
@@ -1002,57 +1008,63 @@
               ippart.substr(24, 4) + ":" +
               ippart.substr(28, 4);
 
-            ComboAddress ca(fulladdress);
-            return ca.toString();
+            ComboAddress address(fulladdress);
+            return address.toString();
           }
         }
+        return allZerosIP;
+      } catch (const PDNSException &e) {
+        return allZerosIP;
       }
-
-      return std::string("::");
     });
-  lua.writeFunction("createReverse6", [](string format, boost::optional<std::unordered_map<string,string>> e){
+  lua.writeFunction("createReverse6", [](const string &format, boost::optional<std::unordered_map<string,string>> excp){
       vector<ComboAddress> candidates;
 
       try {
         auto labels= s_lua_record_ctx->qname.getRawLabels();
-        if(labels.size()<32)
+        if (labels.size()<32) {
           return std::string("unknown");
+	}
         boost::format fmt(format);
         fmt.exceptions( boost::io::all_error_bits ^ ( boost::io::too_many_args_bit | boost::io::too_few_args_bit )  );
 
 
         string together;
         vector<string> quads;
-        for(int i=0; i<8; ++i) {
-          if(i)
-            together+=":";
+        for (int chunk = 0; chunk < 8; ++chunk) {
+          if (chunk != 0) {
+            together += ":";
+	  }
           string lquad;
-          for(int j=0; j <4; ++j) {
-            lquad.append(1, labels[31-i*4-j][0]);
-            together += labels[31-i*4-j][0];
+          for (int quartet = 0; quartet < 4; ++quartet) {
+            lquad.append(1, labels[31 - chunk * 4 - quartet][0]);
+            together += labels[31 - chunk * 4 - quartet][0];
           }
           quads.push_back(lquad);
         }
-        ComboAddress ip6(together,0);
+	ComboAddress ip6(together,0);
 
-        if(e) {
-          auto& addrs=*e;
+	if (excp) {
+          auto& addrs=*excp;
           for(const auto& addr: addrs) {
             // this makes sure we catch all forms of the address
-            if(ComboAddress(addr.first,0)==ip6)
+            if (ComboAddress(addr.first, 0) == ip6) {
               return addr.second;
+	    }
           }
         }
 
         string dashed=ip6.toString();
         boost::replace_all(dashed, ":", "-");
 
-        for(int i=31; i>=0; --i)
-          fmt % labels[i];
+        for (int byte = 31; byte >= 0; --byte) {
+          fmt % labels[byte];
+	}
         fmt % dashed;
 
-        for(const auto& lquad : quads)
+        for(const auto& lquad : quads) {
           fmt % lquad;
+	}
 
         return fmt.str();
       }
diff -Nru pdns-4.9.4/pdns/test-tsig.cc pdns-4.9.7/pdns/test-tsig.cc
--- pdns-4.9.4/pdns/test-tsig.cc	2025-02-06 16:17:38.000000000 +0100
+++ pdns-4.9.7/pdns/test-tsig.cc	2025-07-07 09:42:15.000000000 +0200
@@ -141,6 +141,17 @@
   checkTSIG(tsigName, tsigAlgo.makeLowerCase(), tsigSecret, packet);
 }
 
+BOOST_AUTO_TEST_CASE(test_TSIG_different_case_name) {
+  DNSName tsigName("tsig.Name");
+  DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");
+  DNSName qname("test.valid.tsig");
+  string tsigSecret("verysecret");
+
+  vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret);
+
+  checkTSIG(tsigName.makeLowerCase(), tsigAlgo.makeLowerCase(), tsigSecret, packet);
+}
+
 BOOST_AUTO_TEST_CASE(test_TSIG_different_name_same_algo) {
   DNSName tsigName("tsig.name");
   DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply to: