diff --git a/CHANGES b/CHANGES index 90dea36dd5..691d30b0a4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +3826. [bug] Corrected a use-after-free in isc_radix_remove(). + (This function is not used in BIND, but could have + caused problems in programs linking to libisc.) + [RT #35870] + 3825. [bug] Address sign extension bug in isc_regex_validate. [RT #35758] diff --git a/lib/isc/radix.c b/lib/isc/radix.c index 82090d1fde..df26615fa9 100644 --- a/lib/isc/radix.c +++ b/lib/isc/radix.c @@ -634,12 +634,12 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) { if (node->r == NULL && node->l == NULL) { parent = node->parent; _deref_prefix(node->prefix); - isc_mem_put(radix->mctx, node, sizeof(*node)); - radix->num_active_node--; if (parent == NULL) { INSIST(radix->head == node); radix->head = NULL; + isc_mem_put(radix->mctx, node, sizeof(*node)); + radix->num_active_node--; return; } @@ -652,11 +652,13 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) { child = parent->r; } + isc_mem_put(radix->mctx, node, sizeof(*node)); + radix->num_active_node--; + if (parent->prefix) return; /* We need to remove parent too. */ - if (parent->parent == NULL) { INSIST(radix->head == parent); radix->head = child; @@ -666,6 +668,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) { INSIST(parent->parent->l == parent); parent->parent->l = child; } + child->parent = parent->parent; isc_mem_put(radix->mctx, parent, sizeof(*parent)); radix->num_active_node--; @@ -678,19 +681,23 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) { INSIST(node->l != NULL); child = node->l; } + parent = node->parent; child->parent = parent; _deref_prefix(node->prefix); - isc_mem_put(radix->mctx, node, sizeof(*node)); - radix->num_active_node--; if (parent == NULL) { INSIST(radix->head == node); radix->head = child; + isc_mem_put(radix->mctx, node, sizeof(*node)); + radix->num_active_node--; return; } + isc_mem_put(radix->mctx, node, sizeof(*node)); + radix->num_active_node--; + if (parent->r == node) { parent->r = child; } else {