Commit a59a595d99 for bind

commit a59a595d99571653eb4cbf91c96658bac41b78fa
Author: Colin Vidal <colin@isc.org>
Date:   Thu Jul 9 11:17:50 2026 +0200

    Fix synthrecord dns_message_gettemp*() API usage

    The `dns_message_gettemp*()` API is used to get dynamically allocated
    data owned by a `dns_message_t`, like name, rdata, rdataset and
    rdatalist. If the data is reachable from the message (i.e. the
    name has been added to a section and linked to an rdataset) then it
    is freed automatically when when the message is sent and removed from
    memory, or earlier in some cases, such as truncated responses.

    The `synthrecord` plugin was misusing this API by explicitely freeing
    the data after the message was sent. This was harmless in most
    cases, but could lead to a double-free for the owner name of the
    synthesized record in the event of a truncated response.  This
    double-free was caught early by a failed assertion, causing named
    to crash.

    This is now fixed by allowing the message API to handle freeing of
    message data itself.

diff --git a/bin/plugins/synthrecord.c b/bin/plugins/synthrecord.c
index dbc90b6744..eb2b5a60a4 100644
--- a/bin/plugins/synthrecord.c
+++ b/bin/plugins/synthrecord.c
@@ -122,9 +122,8 @@ static isc_result_t
 synthrecord_respond(synthrecord_t *inst, query_ctx_t *qctx, void *rdata,
 		    dns_rdatatype_t rtype) {
 	isc_result_t result;
-	isc_mem_t *mctx = qctx->client->inner.view->mctx;
 	dns_message_t *msg = qctx->client->message;
-	dns_name_t aname = DNS_NAME_INITEMPTY;
+	dns_name_t *aname = NULL;
 	dns_rdataset_t *synthset = NULL;
 	dns_rdatalist_t *synthlist = NULL;
 	dns_rdata_t *synthdata = NULL;
@@ -136,8 +135,9 @@ synthrecord_respond(synthrecord_t *inst, query_ctx_t *qctx, void *rdata,
 	 */
 	dns_message_gettemprdata(msg, &synthdata);
 	isc_buffer_init(&synthdatab, synthdatabdata, sizeof(synthdatabdata));
-	CHECK(dns_rdata_fromstruct(synthdata, dns_rdataclass_in, rtype, rdata,
-				   &synthdatab));
+	result = dns_rdata_fromstruct(synthdata, dns_rdataclass_in, rtype,
+				      rdata, &synthdatab);
+	INSIST(result == ISC_R_SUCCESS);

 	/*
 	 * Reference synthdata from the rdatalist
@@ -158,10 +158,11 @@ synthrecord_respond(synthrecord_t *inst, query_ctx_t *qctx, void *rdata,
 	 * Then create the name in the ANSWER section and attach the
 	 * rdataset to it.
 	 */
-	dns_name_dup(qctx->client->query.qname, mctx, &aname);
-	dns_message_addname(msg, &aname, DNS_SECTION_ANSWER);
-	dns_rdataset_setownercase(synthset, &aname);
-	ISC_LIST_APPEND(aname.list, synthset, link);
+	dns_message_gettempname(msg, &aname);
+	dns_name_copy(qctx->client->query.qname, aname);
+	dns_message_addname(msg, aname, DNS_SECTION_ANSWER);
+	dns_rdataset_setownercase(synthset, aname);
+	ISC_LIST_APPEND(aname->list, synthset, link);

 	/*
 	 * Send the message with the ANSWER section containing the
@@ -170,21 +171,11 @@ synthrecord_respond(synthrecord_t *inst, query_ctx_t *qctx, void *rdata,
 	result = ns_query_done(qctx);

 	/*
-	 * Message is gone now, let's free message response datastructures
+	 * Message is gone now, intermediate data borrowed from the message
+	 * (name, rdataset, etc.) are automatically released internally. (See
+	 * comment in `lib/dns/message.h` regarding `dns_message_gettemp*()` API
+	 * usage.)
 	 */
-	dns_message_removename(msg, &aname, DNS_SECTION_ANSWER);
-	ISC_LIST_UNLINK(aname.list, synthset, link);
-	dns_name_free(&aname, mctx);
-
-	dns_rdataset_disassociate(synthset);
-	dns_message_puttemprdataset(msg, &synthset);
-
-	ISC_LIST_UNLINK(synthlist->rdata, synthdata, link);
-	dns_message_puttemprdatalist(msg, &synthlist);
-
-cleanup:
-	dns_message_puttemprdata(msg, &synthdata);
-
 	return result;
 }