From acab2c8094fca6230f6219f33b4cbd101e1102dc Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 20 Apr 1999 22:01:00 +0000 Subject: [PATCH] Fixed a bug that resulted when a callback said to halt a search; the level_count was decremented below zero because the found node had not been put in the level history before the callback broke out of the search. Added a bunch of INSISTS()s to try to catch something like that in the future. --- lib/dns/rbt.c | 64 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 99f56a1d12..197f9ef008 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: rbt.c,v 1.44 1999/04/20 18:11:07 tale Exp $ */ +/* $Id: rbt.c,v 1.45 1999/04/20 22:01:00 tale Exp $ */ /* Principal Authors: DCL */ @@ -802,6 +802,22 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname, if (empty_data_ok || DATA(current) != NULL) *node = current; + /* + * Point the chain to the next level. This + * needs to be done before 'current' is pointed + * there because the callback in the next + * block of code needs the current 'current', + * but in the event the callback requests that + * the search be stopped then the + * DNS_R_PARTIALMATCH code at the end of this + * function needs the chain pointed to the + * next level. + */ + + ADD_ANCESTOR(chain, NULL); + ADD_LEVEL(chain, current); + chain->level_matches++; + /* * The caller may want to interrupt the * downward search when certain special nodes @@ -810,15 +826,13 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname, * caller wants to do. */ if (callback != NULL && CALLBACK(current)) { - chain->end = current; result = chain_name(chain, callback_name, - ISC_TRUE); + ISC_FALSE); if (result != DNS_R_SUCCESS) { dns_rbtnodechain_reset(chain); return (result); } - chain->end = NULL; result = (callback)(current, callback_name, @@ -835,12 +849,8 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname, } /* - * Search in the next tree level. + * Finally, head to the next tree level. */ - ADD_ANCESTOR(chain, NULL); - ADD_LEVEL(chain, current); - chain->level_matches++; - current = DOWN(current); } else { @@ -888,8 +898,10 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname, unsigned int saved_count = chain->level_count; while (chain->levels[chain->level_count - 1] != - *node) + *node) { + INSIST(chain->level_count > 1); chain->level_count--; + } result = chain_name(chain, foundname, ISC_FALSE); @@ -915,6 +927,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname, * history. */ + INSIST(chain->ancestor_count > 0); current = chain->ancestors[--chain->ancestor_count]; if (current == NULL) { @@ -926,6 +939,8 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname, * order against, the terminal name is the * predecessor. */ + INSIST(chain->level_count > 0 && + chain->level_matches > 0); chain->end = chain->levels[--chain->level_count]; chain->level_matches--; @@ -1115,6 +1130,7 @@ zapnode_and_fixlevels(dns_rbt_t *rbt, dns_rbtnode_t *node, * item. That item's name can be joined with the name * on this level. */ + INSIST(chain->ancestor_count > 0); rootp = chain->level_count > 0 ? &DOWN(chain->levels[chain->level_count - 1]) : &rbt->root; @@ -1852,16 +1868,14 @@ dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name, REQUIRE(VALID_CHAIN(chain)); + if (node != NULL) + *node = chain->end; + + if (chain->end == NULL) + return (DNS_R_NOTFOUND); + if (name != NULL) { - if (chain->end != NULL) - NODENAME(chain->end, name); - else - /* - * Any offsets are zapped by this call, but they - * would have been redirected anyway if there - * was a chain_end. - */ - dns_name_init(name, NULL); + NODENAME(chain->end, name); if (chain->level_count == 0) { /* @@ -1889,11 +1903,7 @@ dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name, } - if (node != NULL) - *node = chain->end; - return (result); - } dns_result_t @@ -1923,6 +1933,7 @@ dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name, } else { while (chain->ancestors[chain->ancestor_count - 1] != NULL) { + INSIST(chain->ancestor_count > 1); previous = current; current = chain->ancestors[--chain->ancestor_count]; @@ -1970,6 +1981,8 @@ dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name, * Got to the root of this level without having traversed * any right links. Ascend the tree one level. */ + INSIST(chain->level_count > 0 && + chain->ancestor_count > 0); predecessor = chain->levels[--chain->level_count]; chain->ancestor_count--; @@ -2052,6 +2065,7 @@ dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name, do { while (chain->ancestors[chain->ancestor_count - 1] != NULL) { + INSIST(chain->ancestor_count > 1); previous = current; current = chain->ancestors[--chain->ancestor_count]; @@ -2067,8 +2081,10 @@ dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name, * Reached the root without having traversed * any left pointers, so this level is done. */ - chain->ancestor_count--; + INSIST(chain->level_count > 0 && + chain->ancestor_count > 0); current = chain->levels[--chain->level_count]; + chain->ancestor_count--; new_origin = ISC_TRUE; if (RIGHT(current) != NULL)