diff -aur unbound-1.4.17-orig/iterator/iterator.c unbound-1.4.17/iterator/iterator.c --- unbound-1.4.17-orig/iterator/iterator.c 2012-03-21 11:01:01.000000000 -0400 +++ unbound-1.4.17/iterator/iterator.c 2012-07-23 13:29:05.755093317 -0400 @@ -1541,8 +1541,7 @@ * the final state (i.e., on answer). */ static int -processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, - int id) +processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id) { struct module_qstate* subq = NULL; verbose(VERB_ALGO, "processDSNSFind"); @@ -1906,8 +1905,16 @@ if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point && !(iq->chase_flags&BIT_RD) && iter_ds_toolow(iq->response, iq->dp) - && iter_dp_cangodown(&iq->qchase, iq->dp)) + && iter_dp_cangodown(&iq->qchase, iq->dp)) { + /* close down outstanding requests to be discarded */ + outbound_list_clear(&iq->outlist); + iq->num_current_queries = 0; + fptr_ok(fptr_whitelist_modenv_detach_subs( + qstate->env->detach_subs)); + (*qstate->env->detach_subs)(qstate); + iq->num_target_queries = 0; return processDSNSFind(qstate, iq, id); + } if(!iter_dns_store(qstate->env, &iq->response->qinfo, iq->response->rep, 0, qstate->prefetch_leeway, iq->dp&&iq->dp->has_parent_side_NS, @@ -2032,8 +2039,15 @@ if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point && !(iq->chase_flags&BIT_RD) && iter_ds_toolow(iq->response, iq->dp) - && iter_dp_cangodown(&iq->qchase, iq->dp)) + && iter_dp_cangodown(&iq->qchase, iq->dp)) { + outbound_list_clear(&iq->outlist); + iq->num_current_queries = 0; + fptr_ok(fptr_whitelist_modenv_detach_subs( + qstate->env->detach_subs)); + (*qstate->env->detach_subs)(qstate); + iq->num_target_queries = 0; return processDSNSFind(qstate, iq, id); + } /* Process the CNAME response. */ if(!handle_cname_response(qstate, iq, iq->response, &sname, &snamelen)) diff -aur unbound-1.4.17-orig/services/mesh.c unbound-1.4.17/services/mesh.c --- unbound-1.4.17-orig/services/mesh.c 2011-11-10 13:44:06.000000000 -0500 +++ unbound-1.4.17/services/mesh.c 2012-07-23 13:27:08.163096837 -0400 @@ -676,6 +676,7 @@ /* find it, if not, create it */ struct mesh_area* mesh = qstate->env->mesh; struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime); + int was_detached; if(mesh_detect_cycle_found(qstate, sub)) { verbose(VERB_ALGO, "attach failed, cycle detected"); return 0; @@ -706,9 +707,12 @@ *newq = &sub->s; } else *newq = NULL; + was_detached = (sub->super_set.count == 0); if(!mesh_state_attachment(qstate->mesh_info, sub)) return 0; - if(!sub->reply_list && !sub->cb_list && sub->super_set.count == 1) { + /* if it was a duplicate attachment, the count was not zero before */ + if(!sub->reply_list && !sub->cb_list && was_detached && + sub->super_set.count == 1) { /* it used to be detached, before this one got added */ log_assert(mesh->num_detached_states > 0); mesh->num_detached_states--; @@ -735,16 +739,20 @@ superref->s = super; subref->node.key = subref; subref->s = sub; -#ifdef UNBOUND_DEBUG - n = -#endif - rbtree_insert(&sub->super_set, &superref->node); - log_assert(n != NULL); + if(!rbtree_insert(&sub->super_set, &superref->node)) { + /* this should not happen, iterator and validator do not + * attach subqueries that are identical. */ + /* already attached, we are done, nothing todo. + * since superref and subref already allocated in region, + * we cannot free them */ + return 1; + } #ifdef UNBOUND_DEBUG n = #endif rbtree_insert(&super->sub_set, &subref->node); - log_assert(n != NULL); + log_assert(n != NULL); /* we checked above if statement, the reverse + administration should not fail now, unless they are out of sync */ return 1; }