diff --git a/dnscrypt/dnscrypt.c b/dnscrypt/dnscrypt.c
index 4902447fd..173484cdf 100644
--- a/dnscrypt/dnscrypt.c
+++ b/dnscrypt/dnscrypt.c
@@ -361,7 +361,7 @@ dnscrypt_server_uncurve(struct dnsc_env* env,
 
     len -= DNSCRYPT_QUERY_HEADER_SIZE;
 
-    while (*sldns_buffer_at(buffer, --len) == 0)
+    while (len>0 && *sldns_buffer_at(buffer, --len) == 0)
         ;
 
     if (*sldns_buffer_at(buffer, len) != 0x80) {
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
index 37c4150cd..74a258640 100644
--- a/iterator/iter_scrub.c
+++ b/iterator/iter_scrub.c
@@ -777,7 +777,13 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
 			rrset->rrset_all_next = NULL;
 			return 1;
 		}
-		mark_additional_rrset(pkt, msg, rrset);
+		/* Only mark glue as allowed for type NS in the authority
+		 * section. Other RR types do not get glue for them, it
+		 * is allowed from the answer section, but not authority
+		 * so that a message can not have address records cached
+		 * as a side effect to the query. */
+		if(rrset->type==LDNS_RR_TYPE_NS)
+			mark_additional_rrset(pkt, msg, rrset);
 		prev = rrset;
 		rrset = rrset->rrset_all_next;
 	}
diff --git a/services/cache/dns.c b/services/cache/dns.c
index c593dcd72..f6ce272a5 100644
--- a/services/cache/dns.c
+++ b/services/cache/dns.c
@@ -712,10 +712,16 @@ struct dns_msg*
 dns_msg_deepcopy_region(struct dns_msg* origin, struct regional* region)
 {
 	size_t i;
+	struct ub_packed_rrset_key** saved_rrsets;
 	struct dns_msg* res = NULL;
+	size_t rep_alloc_size = sizeof(struct reply_info)
+		- sizeof(struct rrset_ref);  /* this is the size of res->rep
+						allocated in gen_dns_msg() */
 	res = gen_dns_msg(region, &origin->qinfo, origin->rep->rrset_count);
 	if(!res) return NULL;
-	*res->rep = *origin->rep;
+	saved_rrsets = res->rep->rrsets; /* save rrsets alloc by gen_dns_msg */
+	memcpy(res->rep, origin->rep, rep_alloc_size);
+	res->rep->rrsets = saved_rrsets;
 	if(origin->rep->reason_bogus_str) {
 		res->rep->reason_bogus_str = regional_strdup(region,
 			origin->rep->reason_bogus_str);
diff --git a/services/cache/rrset.c b/services/cache/rrset.c
index c1716a565..ab4f4c8e0 100644
--- a/services/cache/rrset.c
+++ b/services/cache/rrset.c
@@ -149,6 +149,16 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
 		if(equal && !TTL_IS_EXPIRED(cached->ttl, timenow) &&
 			cached->security == sec_status_bogus)
 			return 0;
+		/* ghost-domain: never let an NS overwrite extend lifetime
+		 * past the entry it replaces, regardless of trust. */
+		if(ns && !TTL_IS_EXPIRED(cached->ttl, timenow) &&
+			newd->ttl > cached->ttl) {
+			size_t i;
+			newd->ttl = cached->ttl;
+			for(i=0; i<(newd->count+newd->rrsig_count); i++)
+				if(newd->rr_ttl[i] > newd->ttl)
+					newd->rr_ttl[i] = newd->ttl;
+		}
                 return 1;
 	}
 	/*	o item in cache has expired */
diff --git a/services/mesh.c b/services/mesh.c
index 433aabc9c..286901047 100644
--- a/services/mesh.c
+++ b/services/mesh.c
@@ -297,12 +297,14 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
 	if(mesh->num_reply_states < mesh->max_reply_states)
 		return 1;
 	/* try to kick out a jostle-list item */
-	if(m && m->reply_list && m->list_select == mesh_jostle_list) {
+	if(m && m->list_select == mesh_jostle_list) {
 		/* how old is it? */
 		struct timeval age;
-		timeval_subtract(&age, mesh->env->now_tv,
-			&m->reply_list->start_time);
-		if(timeval_smaller(&mesh->jostle_max, &age)) {
+		if(m->has_first_reply_time)
+			timeval_subtract(&age, mesh->env->now_tv,
+				&m->first_reply_time);
+		if(!m->has_first_reply_time ||
+			timeval_smaller(&mesh->jostle_max, &age)) {
 			/* its a goner */
 			log_nametypeclass(VERB_ALGO, "query jostled out to "
 				"make space for a new one",
@@ -1995,6 +1997,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
 	r->qid = qid;
 	r->qflags = qflags;
 	r->start_time = *s->s.env->now_tv;
+	if(s->reply_list == NULL && !s->has_first_reply_time) {
+		s->first_reply_time = r->start_time;
+		s->has_first_reply_time = 1;
+	}
 	r->next = s->reply_list;
 	r->qname = regional_alloc_init(s->s.region, qinfo->qname,
 		s->s.qinfo.qname_len);
diff --git a/services/mesh.h b/services/mesh.h
index d2fac9d3c..9ee585156 100644
--- a/services/mesh.h
+++ b/services/mesh.h
@@ -191,6 +191,12 @@ struct mesh_state {
 	struct module_qstate s;
 	/** the list of replies to clients for the results */
 	struct mesh_reply* reply_list;
+	/** if it has a first reply time */
+	int has_first_reply_time;
+	/** wall-clock time the first client reply was attached;
+	 *  used by mesh_make_new_space() so duplicate retransmits
+	 *  cannot reset jostle aging. */
+	struct timeval first_reply_time;
 	/** the list of callbacks for the results */
 	struct mesh_cb* cb_list;
 	/** set of superstates (that want this state's result) 
diff --git a/services/rpz.c b/services/rpz.c
index d83acbfb0..5121e46b5 100644
--- a/services/rpz.c
+++ b/services/rpz.c
@@ -2469,6 +2469,7 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
 {
 	struct auth_zones* az;
 	struct auth_zone* a;
+	struct dns_msg* ret = NULL;
 	struct clientip_synthesized_rr* raddr = NULL;
 	struct rpz* r = NULL;
 	struct local_zone* z = NULL;
@@ -2512,13 +2513,11 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
 		z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
 						     is->qchase.qclass, &match);
 		if(z != NULL) {
-			lock_rw_unlock(&a->lock);
 			break;
 		}
 
 		raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is);
 		if(raddr != NULL) {
-			lock_rw_unlock(&a->lock);
 			break;
 		}
 		lock_rw_unlock(&a->lock);
@@ -2533,9 +2532,12 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
 		if(z) {
 			lock_rw_unlock(&z->lock);
 		}
-		return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
+		ret = rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
+	} else {
+		ret = rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
 	}
-	return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
+	lock_rw_unlock(&a->lock);
+	return ret;
 }
 
 struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
diff --git a/testcode/unitmain.c b/testcode/unitmain.c
index 79ce45f39..4bc756a07 100644
--- a/testcode/unitmain.c
+++ b/testcode/unitmain.c
@@ -1092,7 +1092,7 @@ static void edns_ede_encode_notxt_fit_test( struct query_info* qinfo,
 {
 	struct edns_data edns;
 	sldns_buffer* pkt;
-	uint16_t edns_field_size, ede_txt_size;
+	size_t edns_field_size, ede_txt_size;
 	int found_ede = 0, found_ede_other = 0, found_ede_txt = 0;
 	int found_other_edns = 0;
 	edns_ede_encode_setup(&edns, region);
@@ -1123,7 +1123,7 @@ static void edns_ede_encode_no_fit_test( struct query_info* qinfo,
 {
 	struct edns_data edns;
 	sldns_buffer* pkt;
-	uint16_t edns_field_size, ede_size, ede_txt_size;
+	size_t edns_field_size, ede_size, ede_txt_size;
 	int found_ede = 0, found_ede_other = 0, found_ede_txt = 0;
 	int found_other_edns = 0;
 	edns_ede_encode_setup(&edns, region);
diff --git a/testdata/val_nsec3_iter_high.rpl b/testdata/val_nsec3_iter_high.rpl
index 2b78f0b7f..703092d89 100644
--- a/testdata/val_nsec3_iter_high.rpl
+++ b/testdata/val_nsec3_iter_high.rpl
@@ -120,12 +120,12 @@ example.com.	IN SOA	ns.example.com. hostmaster.example.com. 2007090400 28800 720
 example.com.    3600    IN      RRSIG   SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
 
 ; closest encloser, H(example.com).
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854}
+b6fuorg741ufili49mg9j4328ig53sqg.example.com. NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig53sqh SOA NS MX DNSKEY RRSIG
+b6fuorg741ufili49mg9j4328ig53sqg.example.com.	3600	IN	RRSIG	NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AJlV5car66lq5f0ASx7W47A/OADkARAXzKt9ZLojXze+FWK9JjAX+eA=
 
-; wildcard denial, H(*.example.com.) = 4f3cnt8cu22tngec382jj4gde4rb47ub
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854}
+; wildcard denial, H(*.example.com.) = k1a2vr9c269jummpru5d68qllbfmtdcb.
+k1a2vr9c269jummpru5d68qllbfmtacb.example.com. NSEC3 1 1 123 aabb00123456bbccdd k1a2vr9c269jummpru5d68qllbfmtgcb A MX RRSIG
+k1a2vr9c269jummpru5d68qllbfmtacb.example.com.	3600	IN	RRSIG	NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AARB9z4C1WZUI3WP3QAR7RJXFnN0qEBkEt8ocudxXzms4/7/2l6NNWc=
 
 ; next closer name, H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3.
 s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG
@@ -152,10 +152,10 @@ SECTION ANSWER
 SECTION AUTHORITY
 example.com.	IN SOA	ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
 example.com.    3600    IN      RRSIG   SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854}
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854}
+b6fuorg741ufili49mg9j4328ig53sqg.example.com. NSEC3 1 1 123 aabb00123456bbccdd b6fuorg741ufili49mg9j4328ig53sqh SOA NS MX DNSKEY RRSIG
+b6fuorg741ufili49mg9j4328ig53sqg.example.com.	3600	IN	RRSIG	NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AJlV5car66lq5f0ASx7W47A/OADkARAXzKt9ZLojXze+FWK9JjAX+eA=
+k1a2vr9c269jummpru5d68qllbfmtacb.example.com. NSEC3 1 1 123 aabb00123456bbccdd k1a2vr9c269jummpru5d68qllbfmtgcb A MX RRSIG
+k1a2vr9c269jummpru5d68qllbfmtacb.example.com.	3600	IN	RRSIG	NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. AARB9z4C1WZUI3WP3QAR7RJXFnN0qEBkEt8ocudxXzms4/7/2l6NNWc=
 s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG
 s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854}
 
diff --git a/testdata/val_nx_nsec3_collision.rpl b/testdata/val_nx_nsec3_collision.rpl
index 87a55f565..1b1f49e80 100644
--- a/testdata/val_nx_nsec3_collision.rpl
+++ b/testdata/val_nx_nsec3_collision.rpl
@@ -89,6 +89,17 @@ ns.example.com.         IN      A       1.2.3.4
 ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
 ENTRY_END
 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com.	IN SOA	ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com.    3600    IN      RRSIG   SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
+ENTRY_END
+
 ; response to DNSKEY priming query
 ENTRY_BEGIN
 MATCH opcode qtype qname
@@ -163,29 +174,11 @@ STEP 2 TIME_PASSES ELAPSE 0.05
 STEP 10 CHECK_ANSWER
 ENTRY_BEGIN
 MATCH all
-REPLY QR RD RA DO NXDOMAIN
+REPLY QR RD RA DO SERVFAIL
 SECTION QUESTION
 www.example.com. IN A
 SECTION ANSWER
 SECTION AUTHORITY
-example.com.	IN SOA	ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
-example.com.    3600    IN      RRSIG   SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3  1 1 123 aabb00123456bbccdd 6md8numosa4q9ugkffdo1bmm82t5j49s A RRSIG
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHndWrEEbuzezs/4lxeiMgEuUsUbAhR72gJgd/Zmhf80yoxCauw9k5OkCw== ;{id = 2854}
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 18 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 19 - 4f3cnt8cu22tngec382jj4gde4rb87ub A RRSIG
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDRwji51WCXJg7W/3+Jx586af5qgAhQPxHegtzu1I/QbvCNrOOON05N1rw== ;{id = 2854}
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 18 -  s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 19 -  s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 00  s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 01  s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 02  s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 20 03  s1unhcti19bkdr98fegs0v46mbu3t4m4 A RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFDLy4GbR8ZaKHATVJGnGxzpsuq60AhQ1/pRbXi1ZbcYohzHgWzNC50fC5A== ;{id = 2854}
-
 SECTION ADDITIONAL
 ENTRY_END
 
diff --git a/testdata/val_nx_nsec3_params.rpl b/testdata/val_nx_nsec3_params.rpl
index dd3ab6b57..59bef2be3 100644
--- a/testdata/val_nx_nsec3_params.rpl
+++ b/testdata/val_nx_nsec3_params.rpl
@@ -88,6 +88,17 @@ ns.example.com.         IN      A       1.2.3.4
 ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
 ENTRY_END
 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com.	IN SOA	ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com.    3600    IN      RRSIG   SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
+ENTRY_END
+
 ; response to DNSKEY priming query
 ENTRY_BEGIN
 MATCH opcode qtype qname
@@ -144,20 +155,11 @@ ENTRY_END
 STEP 10 CHECK_ANSWER
 ENTRY_BEGIN
 MATCH all
-REPLY QR RD RA DO NXDOMAIN
+REPLY QR RD RA DO SERVFAIL
 SECTION QUESTION
 www.example.com. IN A
 SECTION ANSWER
 SECTION AUTHORITY
-example.com.	IN SOA	ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
-example.com.    3600    IN      RRSIG   SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFCNGZ+/OfElYQMCZ77O9Lw9rhk7PAhUAmDcvTAst6Bq83qPq3r6c/Dm1nFc= ;{id = 2854}
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com. NSEC3 1 1 8 - 6md8numosa4q9ugkffdo1bmm82t5j49s SOA NS MX DNSKEY RRSIG
-6md8numosa4q9ugkffdo1bmm82t5j39s.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCz/LkFOFcaQzVnyySW9ZoVUnxh7gIUdxyS9vqVDzo8pGhFU+3YogN2ZRk= ;{id = 2854}
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com. NSEC3 1 1 0 - 4f3cnt8cu22tngec382jj4gde4rb48ub A MX RRSIG
-4f3cnt8cu22tngec382jj4gde4rb46ub.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFHS+i/OB/V/gYmS1eQTXieXIXGjsAhQQ0Ql7TW/hsUklrb0DfoyhVPG95Q== ;{id = 2854}
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com. NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 A MX RRSIG
-s1unhcti19bkdr98fegs0v46mbu3t4m2.example.com.   3600    IN      RRSIG   NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFFSH4klZKke48dYyddYDj17gjTS0AhUAltWicpFLWqW98/Af9Qlx70MH8o4= ;{id = 2854}
-
 SECTION ADDITIONAL
 ENTRY_END
 
diff --git a/util/data/msgencode.c b/util/data/msgencode.c
index 8f4639519..dd56cc6aa 100644
--- a/util/data/msgencode.c
+++ b/util/data/msgencode.c
@@ -352,7 +352,6 @@ compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs,
 		(p = compress_tree_lookup(tree, dname, labs, &insertpt))) {
 		if(!write_compressed_dname(pkt, dname, labs, p))
 			return RETVAL_TRUNC;
-		(*compress_count)++;
 	} else {
 		if(!dname_buffer_write(pkt, dname))
 			return RETVAL_TRUNC;
@@ -360,6 +359,7 @@ compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs,
 	if(*compress_count < MAX_COMPRESSION_PER_MESSAGE &&
 		!compress_tree_store(dname, labs, pos, region, p, insertpt))
 		return RETVAL_OUTMEM;
+	(*compress_count)++;
 	return RETVAL_OK;
 }
 
@@ -820,7 +820,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
 	return 1;
 }
 
-uint16_t
+size_t
 calc_edns_field_size(struct edns_data* edns)
 {
 	size_t rdatalen = 0;
@@ -856,7 +856,7 @@ calc_edns_option_size(struct edns_data* edns, uint16_t code)
 }
 
 uint16_t
-calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size)
+calc_ede_option_size(struct edns_data* edns, size_t* txt_size)
 {
 	size_t rdatalen = 0;
 	struct edns_option* opt;
@@ -958,6 +958,10 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns,
 			padding_option = opt;
 			continue;
 		}
+		if(sldns_buffer_position(pkt) + opt->opt_len + 4 > max_msg_sz)
+			break; /* no space for it */
+		if(!sldns_buffer_available(pkt, 4 + opt->opt_len))
+			break;
 		sldns_buffer_write_u16(pkt, opt->opt_code);
 		sldns_buffer_write_u16(pkt, opt->opt_len);
 		if(opt->opt_len != 0)
@@ -968,12 +972,18 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns,
 			padding_option = opt;
 			continue;
 		}
+		if(sldns_buffer_position(pkt) + opt->opt_len + 4 > max_msg_sz)
+			break; /* no space for it */
+		if(!sldns_buffer_available(pkt, 4 + opt->opt_len))
+			break;
 		sldns_buffer_write_u16(pkt, opt->opt_code);
 		sldns_buffer_write_u16(pkt, opt->opt_len);
 		if(opt->opt_len != 0)
 			sldns_buffer_write(pkt, opt->opt_data, opt->opt_len);
 	}
-	if (padding_option && edns->padding_block_size ) {
+	if (padding_option && edns->padding_block_size &&
+		sldns_buffer_position(pkt)+4 <= max_msg_sz &&
+		sldns_buffer_available(pkt, 4) /* if there is space for it */) {
 		size_t pad_pos = sldns_buffer_position(pkt);
 		size_t msg_sz = ((pad_pos + 3) / edns->padding_block_size + 1)
 		                               * edns->padding_block_size;
@@ -1017,7 +1027,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
 {
 	uint16_t flags;
 	unsigned int attach_edns = 0;
-	uint16_t edns_field_size, ede_size, ede_txt_size;
+	size_t edns_field_size, ede_size, ede_txt_size;
 
 	if(!cached || rep->authoritative) {
 		/* original flags, copy RD and CD bits from query. */
@@ -1044,12 +1054,12 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
 	 * calculate sizes once here */
 	edns_field_size = calc_edns_field_size(edns);
 	ede_size = calc_ede_option_size(edns, &ede_txt_size);
-	if(sldns_buffer_capacity(pkt) < udpsize)
+	if(sldns_buffer_capacity(pkt) < (size_t)udpsize)
 		udpsize = sldns_buffer_capacity(pkt);
 	if(!edns || !edns->edns_present) {
 		attach_edns = 0;
 	/* EDEs are optional, try to fit anything else before them */
-	} else if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) {
+	} else if((size_t)udpsize < (size_t)LDNS_HEADER_SIZE + edns_field_size - ede_size) {
 		/* packet too small to contain edns, omit it. */
 		attach_edns = 0;
 	} else {
@@ -1063,13 +1073,13 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
 		return 0;
 	}
 	if(attach_edns) {
-		if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size)
+		if((size_t)udpsize >= sldns_buffer_limit(pkt) + edns_field_size)
 			attach_edns_record_max_msg_sz(pkt, edns, udpsize);
-		else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_txt_size) {
+		else if((size_t)udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_txt_size) {
 			ede_trim_text(&edns->opt_list_inplace_cb_out);
 			ede_trim_text(&edns->opt_list_out);
 			attach_edns_record_max_msg_sz(pkt, edns, udpsize);
-		} else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_size) {
+		} else if((size_t)udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_size) {
 			edns_opt_list_remove(&edns->opt_list_inplace_cb_out, LDNS_EDNS_EDE);
 			edns_opt_list_remove(&edns->opt_list_out, LDNS_EDNS_EDE);
 			attach_edns_record_max_msg_sz(pkt, edns, udpsize);
@@ -1132,7 +1142,7 @@ extended_error_encode(sldns_buffer* buf, uint16_t rcode,
 	}
 	sldns_buffer_flip(buf);
 	if(edns && edns->edns_present) {
-		uint16_t edns_field_size, ede_size, ede_txt_size;
+		size_t edns_field_size, ede_size, ede_txt_size;
 		struct edns_data es = *edns;
 		es.edns_version = EDNS_ADVERTISED_VERSION;
 		es.udp_size = EDNS_ADVERTISED_SIZE;
@@ -1144,13 +1154,13 @@ extended_error_encode(sldns_buffer* buf, uint16_t rcode,
 		 * to see if EDNS can fit. */
 		edns_field_size = calc_edns_field_size(&es);
 		ede_size = calc_ede_option_size(&es, &ede_txt_size);
-		if(edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size)
+		if((size_t)edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size)
 			attach_edns_record_max_msg_sz(buf, &es, edns->udp_size);
-		else if(edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size - ede_txt_size) {
+		else if((size_t)edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size - ede_txt_size) {
 			ede_trim_text(&es.opt_list_inplace_cb_out);
 			ede_trim_text(&es.opt_list_out);
 			attach_edns_record_max_msg_sz(buf, &es, edns->udp_size);
-		} else if(edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size - ede_size) {
+		} else if((size_t)edns->udp_size >= sldns_buffer_limit(buf) + edns_field_size - ede_size) {
 			edns_opt_list_remove(&es.opt_list_inplace_cb_out, LDNS_EDNS_EDE);
 			edns_opt_list_remove(&es.opt_list_out, LDNS_EDNS_EDE);
 			attach_edns_record_max_msg_sz(buf, &es, edns->udp_size);
diff --git a/util/data/msgencode.h b/util/data/msgencode.h
index 0363a90bf..f561fe1dd 100644
--- a/util/data/msgencode.h
+++ b/util/data/msgencode.h
@@ -106,7 +106,7 @@ void qinfo_query_encode(struct sldns_buffer* pkt, struct query_info* qinfo);
  * @param edns: edns data or NULL.
  * @return octets to reserve for EDNS.
  */
-uint16_t calc_edns_field_size(struct edns_data* edns);
+size_t calc_edns_field_size(struct edns_data* edns);
 
 /**
  * Calculate the size of a specific EDNS option in packet.
@@ -127,7 +127,7 @@ uint16_t calc_edns_option_size(struct edns_data* edns, uint16_t code);
  *	extra text.
  * @return octets the option will take up.
  */
-uint16_t calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size);
+uint16_t calc_ede_option_size(struct edns_data* edns, size_t* txt_size);
 
 /**
  * Attach EDNS record to buffer. Buffer has complete packet. There must
diff --git a/util/data/msgparse.c b/util/data/msgparse.c
index afbcbca5b..9239f8fe3 100644
--- a/util/data/msgparse.c
+++ b/util/data/msgparse.c
@@ -53,6 +53,8 @@
 #include "sldns/parseutil.h"
 #include "sldns/wire2str.h"
 
+#define MAX_PARSED_EDNS_OPTIONS 100
+
 /** smart comparison of (compressed, valid) dnames from packet */
 static int
 smart_compare(sldns_buffer* pkt, uint8_t* dnow, 
@@ -950,6 +952,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
 	struct comm_reply* repinfo, uint32_t now, struct regional* region,
 	struct cookie_secrets* cookie_secrets)
 {
+	int i = 0, nsid_seen = 0, cookie_seen = 0, padding_seen = 0;
 	/* To respond with a Keepalive option, the client connection must have
 	 * received one message with a TCP Keepalive EDNS option, and that
 	 * option must have 0 length data. Subsequent messages sent on that
@@ -969,7 +972,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
 
 	/* while still more options, and have code+len to read */
 	/* ignores partial content (i.e. rdata len 3) */
-	while(rdata_len >= 4) {
+	while(rdata_len >= 4 && i < MAX_PARSED_EDNS_OPTIONS) {
 		uint16_t opt_code = sldns_read_uint16(rdata_ptr);
 		uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
 		uint8_t server_cookie[40];
@@ -984,8 +987,9 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
 		/* handle parse time edns options here */
 		switch(opt_code) {
 		case LDNS_EDNS_NSID:
-			if (!cfg || !cfg->nsid)
+			if (!cfg || !cfg->nsid || nsid_seen)
 				break;
+			nsid_seen = 1;
 			if(!edns_opt_list_append(&edns->opt_list_out,
 						LDNS_EDNS_NSID, cfg->nsid_len,
 						cfg->nsid, region)) {
@@ -1027,8 +1031,9 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
 
 		case LDNS_EDNS_PADDING:
 			if(!cfg || !cfg->pad_responses ||
-					!c || c->type != comm_tcp ||!c->ssl)
+					!c || c->type != comm_tcp ||!c->ssl || padding_seen)
 				break;
+			padding_seen = 1;
 			if(!edns_opt_list_append(&edns->opt_list_out,
 						LDNS_EDNS_PADDING,
 						0, NULL, region)) {
@@ -1039,8 +1044,9 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
 			break;
 
 		case LDNS_EDNS_COOKIE:
-			if(!cfg || !cfg->do_answer_cookie || !repinfo)
+			if(!cfg || !cfg->do_answer_cookie || !repinfo || cookie_seen)
 				break;
+			cookie_seen = 1;
 			if(opt_len != 8 && (opt_len < 16 || opt_len > 40)) {
 				verbose(VERB_ALGO, "worker request: "
 					"badly formatted cookie");
@@ -1146,6 +1152,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
 		}
 		rdata_ptr += opt_len;
 		rdata_len -= opt_len;
+		i++;
 	}
 	return LDNS_RCODE_NOERROR;
 }
@@ -1160,6 +1167,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
 	struct rrset_parse* found_prev = 0;
 	size_t rdata_len;
 	uint8_t* rdata_ptr;
+	int i = 0;
 	/* since the class encodes the UDP size, we cannot use hash table to
 	 * find the EDNS OPT record. Scan the packet. */
 	while(rrset) {
@@ -1219,7 +1227,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
 
 	/* while still more options, and have code+len to read */
 	/* ignores partial content (i.e. rdata len 3) */
-	while(rdata_len >= 4) {
+	while(rdata_len >= 4 && i < MAX_PARSED_EDNS_OPTIONS) {
 		uint16_t opt_code = sldns_read_uint16(rdata_ptr);
 		uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
 		rdata_ptr += 4;
@@ -1234,6 +1242,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
 		}
 		rdata_ptr += opt_len;
 		rdata_len -= opt_len;
+		i++;
 	}
 	/* ignore rrsigs */
 	return LDNS_RCODE_NOERROR;
diff --git a/validator/val_neg.c b/validator/val_neg.c
index 66fd81899..e82f335b9 100644
--- a/validator/val_neg.c
+++ b/validator/val_neg.c
@@ -62,6 +62,13 @@
 #include "sldns/rrdef.h"
 #include "sldns/sbuffer.h"
 
+/**
+ * The maximum salt length that the negative cache is willing to use.
+ * Larger salt increases the computation time, while recommendations are
+ * for zero salt length for zones.
+ */
+#define MAX_SALT_LENGTH 64
+
 int val_neg_data_compare(const void* a, const void* b)
 {
 	struct val_neg_data* x = (struct val_neg_data*)a;
@@ -826,7 +833,11 @@ void neg_insert_data(struct val_neg_cache* neg,
 			(slen != 0 && zone->nsec3_salt && s
 			  && memcmp(zone->nsec3_salt, s, slen) != 0))) {
 
-			if(slen > 0) {
+			if(slen > MAX_SALT_LENGTH) {
+				/* RFC 9276 s3.1: operators SHOULD NOT use a salt; large
+				 * salts inflate per-hash block count. Decline to cache. */
+				return;
+			} else if(slen > 0) {
 				uint8_t* sa = memdup(s, slen);
 				if(sa) {
 					free(zone->nsec3_salt);
@@ -1165,6 +1176,15 @@ neg_find_nsec3_ce(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
 	uint8_t hashce[NSEC3_SHA_LEN];
 	uint8_t b32[257];
 	size_t celen, b32len;
+	int hashmax = MAX_NSEC3_CALCULATIONS;
+	if(qlabs > hashmax) {
+		/* strip leading labels so the walk costs at most
+		 * MAX_NSEC3_CALCULATIONS hashes, mirroring val_nsec3.c */
+		while(qlabs > hashmax) {
+			dname_remove_label(&qname, &qname_len);
+			qlabs--;
+		}
+	}
 
 	*nclen = 0;
 	while(qlabs > 0) {
@@ -1265,6 +1285,12 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
 	if(!zone->nsec3_hash) 
 		return NULL; /* not nsec3 zone */
 
+	if(!topname && qlabs > zone->labs + 1)
+		return NULL; /* iterator caller; opt-out proof would be discarded
+			     * at the !topname check below anyway.
+			     * The qlabs check allows the exact-match for
+			     * the one-label-below-zone case. */
+
 	if(!(data=neg_find_nsec3_ce(zone, qname, qname_len, qlabs, buf,
 		hashnc, &nclen))) {
 		return NULL;
diff --git a/validator/val_nsec3.c b/validator/val_nsec3.c
index 998fcc4e3..62effde20 100644
--- a/validator/val_nsec3.c
+++ b/validator/val_nsec3.c
@@ -59,11 +59,6 @@
 #include "sldns/sbuffer.h"
 #include "util/config_file.h"
 
-/**
- * Max number of NSEC3 calculations at once, suspend query for later.
- * 8 is low enough and allows for cases where multiple proofs are needed.
- */
-#define MAX_NSEC3_CALCULATIONS 8
 /**
  * When all allowed NSEC3 calculations at once resulted in error treat as
  * bogus. NSEC3 hash errors are not cached and this helps breaks loops with
@@ -456,6 +451,67 @@ filter_init(struct nsec3_filter* filter, struct ub_packed_rrset_key** list,
 	}
 }
 
+/** Check if the NSEC3s have the same parameter set. */
+static int
+param_set_same(struct nsec3_filter* flt, char** reason)
+{
+	size_t rrsetnum;
+	int rrnum;
+	struct ub_packed_rrset_key* rrset;
+	int have_params = 0;
+	int first_algo = 0;
+	size_t first_iter = 0;
+	uint8_t* first_salt = NULL;
+	size_t first_saltlen = 0;
+
+	/* If the NSEC3 parameter sets have distinct values, then they are
+	 * from different NSEC3 chains, and we do not want that. */
+	for(rrset=filter_first(flt, &rrsetnum, &rrnum); rrset;
+		rrset=filter_next(flt, &rrsetnum, &rrnum)) {
+		if(!have_params) {
+			first_algo = nsec3_get_algo(rrset, rrnum);
+			first_iter = nsec3_get_iter(rrset, rrnum);
+			if(!nsec3_get_salt(rrset, rrnum, &first_salt,
+				&first_saltlen)) {
+				verbose(VERB_ALGO, "NSEC3 salt malformed");
+				if(reason)
+					*reason = "NSEC3 salt malformed";
+				return 0;
+			}
+			have_params = 1;
+		} else {
+			uint8_t* salt = NULL;
+			size_t saltlen = 0;
+			if(nsec3_get_algo(rrset, rrnum) != first_algo) {
+				verbose(VERB_ALGO, "NSEC3 algorithm mismatch");
+				if(reason)
+					*reason = "NSEC3 algorithm mismatch";
+				return 0;
+			}
+			if(nsec3_get_iter(rrset, rrnum) != first_iter) {
+				verbose(VERB_ALGO, "NSEC3 iterations mismatch");
+				if(reason)
+					*reason = "NSEC3 iterations mismatch";
+				return 0;
+			}
+			if(!nsec3_get_salt(rrset, rrnum, &salt, &saltlen)) {
+				verbose(VERB_ALGO, "NSEC3 salt malformed");
+				if(reason)
+					*reason = "NSEC3 salt malformed";
+				return 0;
+			}
+			if(saltlen != first_saltlen ||
+				memcmp(salt, first_salt, saltlen) != 0) {
+				verbose(VERB_ALGO, "NSEC3 salt mismatch");
+				if(reason)
+					*reason = "NSEC3 salt mismatch";
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
 /**
  * Find max iteration count using config settings and key size
  * @param ve: validator environment with iteration count config settings.
@@ -1192,6 +1248,8 @@ nsec3_prove_nameerror(struct module_env* env, struct val_env* ve,
 	filter_init(&flt, list, num, qinfo); /* init RR iterator */
 	if(!flt.zone)
 		return sec_status_bogus; /* no RRs */
+	if(!param_set_same(&flt, NULL))
+		return sec_status_bogus; /* nsec3 params from distinct chains*/
 	if(nsec3_iteration_count_high(ve, &flt, kkey))
 		return sec_status_insecure; /* iteration count too high */
 	log_nametypeclass(VERB_ALGO, "start nsec3 nameerror proof, zone", 
@@ -1378,6 +1436,8 @@ nsec3_prove_nodata(struct module_env* env, struct val_env* ve,
 	filter_init(&flt, list, num, qinfo); /* init RR iterator */
 	if(!flt.zone)
 		return sec_status_bogus; /* no RRs */
+	if(!param_set_same(&flt, NULL))
+		return sec_status_bogus; /* nsec3 params from distinct chains*/
 	if(nsec3_iteration_count_high(ve, &flt, kkey))
 		return sec_status_insecure; /* iteration count too high */
 	return nsec3_do_prove_nodata(env, &flt, ct, qinfo, calc);
@@ -1401,6 +1461,8 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
 	filter_init(&flt, list, num, qinfo); /* init RR iterator */
 	if(!flt.zone)
 		return sec_status_bogus; /* no RRs */
+	if(!param_set_same(&flt, NULL))
+		return sec_status_bogus; /* nsec3 params from distinct chains*/
 	if(nsec3_iteration_count_high(ve, &flt, kkey))
 		return sec_status_insecure; /* iteration count too high */
 
@@ -1503,6 +1565,8 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
 		*reason = "no NSEC3 records";
 		return sec_status_bogus; /* no RRs */
 	}
+	if(!param_set_same(&flt, reason))
+		return sec_status_bogus; /* nsec3 params from distinct chains*/
 	if(nsec3_iteration_count_high(ve, &flt, kkey))
 		return sec_status_insecure; /* iteration count too high */
 
@@ -1596,6 +1660,8 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
 	filter_init(&flt, list, num, qinfo); /* init RR iterator */
 	if(!flt.zone)
 		return sec_status_bogus; /* no RRs */
+	if(!param_set_same(&flt, NULL))
+		return sec_status_bogus; /* nsec3 params from distinct chains*/
 	if(nsec3_iteration_count_high(ve, &flt, kkey))
 		return sec_status_insecure; /* iteration count too high */
 
diff --git a/validator/val_nsec3.h b/validator/val_nsec3.h
index f668a270f..a13e92991 100644
--- a/validator/val_nsec3.h
+++ b/validator/val_nsec3.h
@@ -98,6 +98,12 @@ struct sldns_buffer;
 /** The SHA1 hash algorithm for NSEC3 */
 #define NSEC3_HASH_SHA1	0x01
 
+/**
+ * Max number of NSEC3 calculations at once, suspend query for later.
+ * 8 is low enough and allows for cases where multiple proofs are needed.
+ */
+#define MAX_NSEC3_CALCULATIONS 8
+
 /**
 * Cache table for NSEC3 hashes.
 * It keeps a *pointer* to the region its items are allocated.
diff --git a/validator/val_utils.c b/validator/val_utils.c
index 411a63b25..8e4c91900 100644
--- a/validator/val_utils.c
+++ b/validator/val_utils.c
@@ -1066,10 +1066,10 @@ val_fill_reply(struct reply_info* chase, struct reply_info* orig,
 			if(query_dname_compare(name, 
 				orig->rrsets[i]->rk.dname) == 0)
 			    chase->rrsets[chase->an_numrrsets
-				+orig->ns_numrrsets+chase->ar_numrrsets++] 
+				+chase->ns_numrrsets+chase->ar_numrrsets++]
 				= orig->rrsets[i];
 		} else if(rrset_has_signer(orig->rrsets[i], name, len)) {
-			chase->rrsets[chase->an_numrrsets+orig->ns_numrrsets+
+			chase->rrsets[chase->an_numrrsets+chase->ns_numrrsets+
 				chase->ar_numrrsets++] = orig->rrsets[i];
 		}
 	}
