Commit bb8c6d045a for bind
commit bb8c6d045a4e4a5d7f2900b8b1d8f7a747e92fae
Author: Alessio Podda <alessio@isc.org>
Date: Mon Aug 10 15:37:26 2026 +0200
Sort unscheduled headers last in the resign heap
Treat headers without the RESIGN attribute as having an effective
resign time of INT64_MAX. This prevents defensive heap entries from
affecting the next scheduled resign time.
diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c
index d30add29fc..488ea5a964 100644
--- a/lib/dns/qpzone.c
+++ b/lib/dns/qpzone.c
@@ -657,9 +657,15 @@ resign_sooner_values(int64_t lhs_resign, dns_typepair_t lhs_typepair,
(lhs_resign == rhs_resign && lhs_is_soa < rhs_is_soa);
}
+static int64_t
+resign_effective_time(const dns_vecheader_t *header) {
+ return RESIGN(header) ? header->resign : INT64_MAX;
+}
+
/*%
* Return which RRset should be resigned sooner. If the RRsets have the
- * same signing time, prefer the other RRset over the SOA RRset.
+ * same signing time, prefer the other RRset over the SOA RRset. Headers
+ * which are not scheduled for resigning sort after every scheduled header.
*/
static bool
resign_sooner(void *v1, void *v2) {
@@ -667,8 +673,8 @@ resign_sooner(void *v1, void *v2) {
qpz_resign_t *elem2 = v2;
return resign_sooner_values(
- elem1->header->resign, elem1->header->typepair,
- elem2->header->resign, elem2->header->typepair);
+ resign_effective_time(elem1->header), elem1->header->typepair,
+ resign_effective_time(elem2->header), elem2->header->typepair);
}
/*%
@@ -2562,9 +2568,9 @@ again:
goto again;
}
- if (elem != NULL) {
+ if (elem != NULL && RESIGN(elem->header)) {
header = elem->header;
- *resign = RESIGN(header) ? (uint32_t)header->resign : 0;
+ *resign = (uint32_t)header->resign;
dns_name_copy(&elem->node->name, foundname);
*typepair = header->typepair;
result = ISC_R_SUCCESS;
diff --git a/tests/dns/qpzone_test.c b/tests/dns/qpzone_test.c
index 5313bab0a2..56a3f44fec 100644
--- a/tests/dns/qpzone_test.c
+++ b/tests/dns/qpzone_test.c
@@ -390,6 +390,17 @@ ISC_RUN_TEST_IMPL(setownercase) {
ISC_RUN_TEST_IMPL(resign_sooner_values) {
dns_typepair_t soa = DNS_SIGTYPEPAIR(dns_rdatatype_soa);
dns_typepair_t other = DNS_SIGTYPEPAIR(dns_rdatatype_a);
+ dns_vecheader_t scheduled = {
+ .attributes = DNS_VECHEADERATTR_RESIGN,
+ .typepair = other,
+ .resign = 20,
+ };
+ dns_vecheader_t unscheduled = {
+ .typepair = other,
+ .resign = 0,
+ };
+ qpz_resign_t scheduled_elem = { .header = &scheduled };
+ qpz_resign_t unscheduled_elem = { .header = &unscheduled };
UNUSED(state);
@@ -401,6 +412,58 @@ ISC_RUN_TEST_IMPL(resign_sooner_values) {
assert_false(resign_sooner_values(10, soa, 10, soa));
assert_false(resign_sooner_values(10, other, 10, other));
+
+ assert_true(resign_sooner(&scheduled_elem, &unscheduled_elem));
+ assert_false(resign_sooner(&unscheduled_elem, &scheduled_elem));
+}
+
+ISC_RUN_TEST_IMPL(unscheduled_resign) {
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_fixedname_t fixed;
+ dns_typepair_t typepair;
+ isc_stdtime_t resign;
+
+ result = dns__qpzone_create(isc_g_mctx, &example_org_name,
+ dns_dbtype_zone, dns_rdataclass_in, 0, NULL,
+ NULL, &db);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ WITH_NEWVERSION(db, version, true) {
+ result = apply_dns_update(db, version, &example_org_name,
+ dns_rdatatype_aaaa, dns_rdataclass_in,
+ 300, aaaa_test_data[0], 16,
+ DNS_DIFFOP_ADD);
+ assert_int_equal(result, ISC_R_SUCCESS);
+ }
+
+ WITH_NEWVERSION(db, version, true) {
+ result = apply_dns_update(db, version, &example_org_name,
+ dns_rdatatype_aaaa, dns_rdataclass_in,
+ 300, aaaa_test_data[1], 16,
+ DNS_DIFFOP_ADD);
+ assert_int_equal(result, ISC_R_SUCCESS);
+ }
+
+ /*
+ * Rolling back the subtraction currently leaves the old, ordinary
+ * AAAA header in the resigning heap. It must not be exposed as a
+ * scheduled header with resign time zero.
+ */
+ WITH_NEWVERSION(db, version, false) {
+ result = apply_dns_update(db, version, &example_org_name,
+ dns_rdatatype_aaaa, dns_rdataclass_in,
+ 300, aaaa_test_data[0], 16,
+ DNS_DIFFOP_DEL);
+ assert_int_equal(result, ISC_R_SUCCESS);
+ }
+
+ dns_fixedname_init(&fixed);
+ result = dns_db_getsigningtime(db, &resign, dns_fixedname_name(&fixed),
+ &typepair);
+ assert_int_equal(result, ISC_R_NOTFOUND);
+
+ dns_db_detach(&db);
}
ISC_RUN_TEST_IMPL(diffop_add_sub) {
@@ -806,6 +869,7 @@ ISC_TEST_LIST_START
ISC_TEST_ENTRY(ownercase)
ISC_TEST_ENTRY(setownercase)
ISC_TEST_ENTRY(resign_sooner_values)
+ISC_TEST_ENTRY(unscheduled_resign)
ISC_TEST_ENTRY(diffop_add_sub)
ISC_TEST_ENTRY(wildcard_foundname)
ISC_TEST_ENTRY(wildcard_delegation_foundname)