Commit 7f90ce6470 for bind

commit 7f90ce647066352d7aa6def4c802574f0dc62bbb
Author: Alessio Podda <alessio@isc.org>
Date:   Wed Aug 19 16:01:57 2026 +0200

    Remove NONEXISTENT attribute

    Simplify rdatavec further by representing tombstones as empty
    rdatavecs.

diff --git a/lib/dns/include/dns/rdatavec.h b/lib/dns/include/dns/rdatavec.h
index 3d9225d0a2..4a80e96240 100644
--- a/lib/dns/include/dns/rdatavec.h
+++ b/lib/dns/include/dns/rdatavec.h
@@ -126,7 +126,6 @@ struct dns_vecheader {
 };

 enum {
-	DNS_VECHEADERATTR_NONEXISTENT = 1 << 0,
 	DNS_VECHEADERATTR_IGNORE = 1 << 1,
 	DNS_VECHEADERATTR_RESIGN = 1 << 2,
 	DNS_VECHEADERATTR_OPTOUT = 1 << 3,
diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c
index d6310420fe..9ab890fbe2 100644
--- a/lib/dns/qpzone.c
+++ b/lib/dns/qpzone.c
@@ -5188,8 +5188,6 @@ qpzone_subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode,
 			newheader = dns_vecheader_new(db->mctx);
 			newheader->ttl = 0;
 			newheader->typepair = foundtop->typepair;
-			atomic_init(&newheader->attributes,
-				    DNS_VECHEADERATTR_NONEXISTENT);
 			newheader->serial = version->serial;
 		} else {
 			LOCK(&qpdb->heap->lock);
@@ -5276,7 +5274,6 @@ qpzone_deleterdataset(dns_db_t *db, dns_dbnode_t *dbnode,
 	newheader = dns_vecheader_new(db->mctx);
 	newheader->typepair = DNS_TYPEPAIR_VALUE(type, covers);
 	newheader->ttl = 0;
-	atomic_init(&newheader->attributes, DNS_VECHEADERATTR_NONEXISTENT);
 	newheader->serial = version->serial;

 	dns_name_copy(&node->name, nodename);
diff --git a/lib/dns/rdatavec.c b/lib/dns/rdatavec.c
index ac66b70e0e..19d7ed476d 100644
--- a/lib/dns/rdatavec.c
+++ b/lib/dns/rdatavec.c
@@ -46,10 +46,7 @@
  *		data		(data length bytes)
  *
  * A "bare" rdatavec is everything after the header. The first two bytes
- * contain the count of rdata records in the rdatavec. For records with
- * the DNS_VECHEADERATTR_NONEXISTENT attribute, the record count is omitted
- * entirely.
- *
+ * contain the count of rdata records in the rdatavec.
  * After the count, the rdata records are stored sequentially in memory.
  * Each record consists of a length field, optional metadata, and the actual
  * rdata bytes.
@@ -427,8 +424,8 @@ typedef struct vecmerge_iter {
 static void
 vecmerge_first(vecmerge_iter_t *iter, dns_vecheader_t *left,
 	       dns_vecheader_t *right, dns_rdataclass_t rdclass) {
-	INSIST(vecheader_first(&iter->left, left, rdclass) == ISC_R_SUCCESS);
-	INSIST(vecheader_first(&iter->right, right, rdclass) == ISC_R_SUCCESS);
+	(void)vecheader_first(&iter->left, left, rdclass);
+	(void)vecheader_first(&iter->right, right, rdclass);
 }

 static bool
@@ -513,8 +510,6 @@ dns_rdatavec_merge(dns_vecheader_t *oheader, dns_vecheader_t *nheader,
 	ocount = rdatavec_count(oheader);
 	ncount = rdatavec_count(nheader);

-	INSIST(ocount > 0 && ncount > 0);
-
 	if (maxrrperset > 0 && ocount + ncount > maxrrperset) {
 		return DNS_R_TOOMANYRECORDS;
 	}
@@ -625,8 +620,6 @@ dns_rdatavec_subtract(dns_vecheader_t *oheader, dns_vecheader_t *sheader,
 	ocount = rdatavec_count(oheader);
 	scount = rdatavec_count(sheader);

-	INSIST(ocount > 0 && scount > 0);
-
 	vecmerge_first(&iter, oheader, sheader, rdclass);

 	while (vecsubtract_next(&iter, &rdata)) {
@@ -736,11 +729,12 @@ dns_vecheader_t *
 dns_vecheader_new(isc_mem_t *mctx) {
 	dns_vecheader_t *h = NULL;

-	h = isc_mem_get(mctx, sizeof(*h));
+	h = isc_mem_get(mctx, sizeof(*h) + sizeof(uint16_t));
 	*h = (dns_vecheader_t){
 		.references = ISC_REFCOUNT_INITIALIZER(1),
 		.mctx = isc_mem_ref(mctx),
 	};
+	ISC_U16TO8_BE(h->raw, 0);
 	return h;
 }

@@ -922,10 +916,7 @@ dns_vectop_destroy(isc_mem_t *mctx, dns_vectop_t **topp) {

 static void
 vecheader_destroy(dns_vecheader_t *header) {
-	unsigned int size = EXISTS(header) ? dns_rdatavec_size(header)
-					   : sizeof(*header);
-
-	isc_mem_putanddetach(&header->mctx, header, size);
+	isc_mem_putanddetach(&header->mctx, header, dns_rdatavec_size(header));
 }

 /*
diff --git a/lib/dns/rdatavec_p.h b/lib/dns/rdatavec_p.h
index b2e93e73a2..98a0b8faa6 100644
--- a/lib/dns/rdatavec_p.h
+++ b/lib/dns/rdatavec_p.h
@@ -17,15 +17,15 @@

 #include <dns/rdatavec.h>

+#define peek_uint16(buffer) ISC_U8TO16_BE(buffer)
+
 #define CASEFULLYLOWER(header)                         \
 	((atomic_load_acquire(&(header)->attributes) & \
 	  DNS_VECHEADERATTR_CASEFULLYLOWER) != 0)
 #define CASESET(header)                                \
 	((atomic_load_acquire(&(header)->attributes) & \
 	  DNS_VECHEADERATTR_CASESET) != 0)
-#define EXISTS(header)                                 \
-	((atomic_load_acquire(&(header)->attributes) & \
-	  DNS_VECHEADERATTR_NONEXISTENT) == 0)
+#define EXISTS(header) (peek_uint16((header)->raw) != 0)
 #define IGNORE(header)                                 \
 	((atomic_load_acquire(&(header)->attributes) & \
 	  DNS_VECHEADERATTR_IGNORE) != 0)
@@ -36,7 +36,6 @@
 	((atomic_load_acquire(&(header)->attributes) & \
 	  DNS_VECHEADERATTR_RESIGN) != 0)

-#define peek_uint16(buffer) ISC_U8TO16_BE(buffer)
 #define get_uint16(buffer)                            \
 	({                                            \
 		uint16_t __ret = peek_uint16(buffer); \
diff --git a/tests/dns/vecheader_test.c b/tests/dns/vecheader_test.c
index e798a0fb21..44d674d59e 100644
--- a/tests/dns/vecheader_test.c
+++ b/tests/dns/vecheader_test.c
@@ -102,6 +102,45 @@ create_rdataset_from_vecheader(dns_vecheader_t *header,
 	rdataset->vec.header = header;
 }

+ISC_RUN_TEST_IMPL(zero_count_vecheader) {
+	isc_mem_t *mctx = isc_g_mctx;
+	dns_vecheader_t *empty = NULL, *header = NULL, *merged = NULL;
+	isc_result_t result;
+
+	UNUSED(state);
+
+	empty = dns_vecheader_new(mctx);
+	empty->typepair = DNS_TYPEPAIR_VALUE(dns_rdatatype_a,
+					     dns_rdatatype_none);
+
+	assert_int_equal(dns_rdatavec_count(empty), 0);
+	assert_int_equal(dns_rdatavec_size(empty),
+			 sizeof(dns_vecheader_t) + sizeof(uint16_t));
+
+	CHECK(create_vecheader(mctx, dns_rdatatype_a, dns_rdataclass_in, 300,
+			       "192.0.2.1", &header));
+	CHECK(dns_rdatavec_merge(empty, header, mctx, dns_rdataclass_in,
+				 dns_rdatatype_a, 0, 0, &merged));
+	assert_int_equal(dns_rdatavec_count(merged), 1);
+	dns_vecheader_unref(merged);
+	merged = NULL;
+
+	result = dns_rdatavec_subtract(header, empty, mctx, dns_rdataclass_in,
+				       dns_rdatatype_a, 0, &merged);
+	assert_int_equal(result, DNS_R_UNCHANGED);
+
+cleanup:
+	if (empty != NULL) {
+		dns_vecheader_unref(empty);
+	}
+	if (header != NULL) {
+		dns_vecheader_unref(header);
+	}
+	if (merged != NULL) {
+		dns_vecheader_unref(merged);
+	}
+}
+
 /* Test merging two headers */
 ISC_RUN_TEST_IMPL(merge_headers) {
 	isc_mem_t *mctx = isc_g_mctx;
@@ -550,6 +589,7 @@ cleanup:
 }

 ISC_TEST_LIST_START
+ISC_TEST_ENTRY_CUSTOM(zero_count_vecheader, setup_mctx, teardown_mctx)
 ISC_TEST_ENTRY_CUSTOM(merge_headers, setup_mctx, teardown_mctx)
 ISC_TEST_ENTRY_CUSTOM(merge_case_preservation, setup_mctx, teardown_mctx)
 ISC_TEST_ENTRY_CUSTOM(setcase_size_consistency, setup_mctx, teardown_mctx)