Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: fix accounting in chash.c
To:
tech@openbsd.org
Date:
Thu, 7 May 2026 11:04:35 +0200

Download raw body.

Thread
The accounting in chash.c has two issues:

- ch_table_resize() did not increase the global
  type->t_counts->cc_num_extendible value and so a later _ch_destroy()
  would underflow the accounting.

- ch_sub_free() can be called with NULL, NULL arguments and then the
  accounting needs to be skipped.

Fixing these issues is trivial.
-- 
:wq Claudio

Index: chash.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/chash.c,v
diff -u -p -r1.9 chash.c
--- chash.c	17 Mar 2026 10:31:03 -0000	1.9
+++ chash.c	6 May 2026 08:45:47 -0000
@@ -512,8 +512,10 @@ static void
 ch_sub_free(const struct ch_type *type, struct ch_table *t,
     struct ch_group *table, struct ch_meta *meta)
 {
-	t->ch_counts.cc_num_tables--;
-	type->t_counts->cc_num_tables--;
+	if (table != NULL) {
+		t->ch_counts.cc_num_tables--;
+		type->t_counts->cc_num_tables--;
+	}
 	free(table);
 	free(meta);
 }
@@ -523,7 +525,7 @@ ch_sub_free(const struct ch_type *type, 
  * Return 0 on success, -1 on failure and set errno.
  */
 static int
-ch_table_resize(struct ch_table *t)
+ch_table_resize(const struct ch_type *type, struct ch_table *t)
 {
 	struct ch_group **tables;
 	struct ch_meta **metas;
@@ -563,6 +565,7 @@ ch_table_resize(struct ch_table *t)
 	t->ch_metas = metas;
 
 	t->ch_counts.cc_num_extendible += oldsize;
+	type->t_counts->cc_num_extendible += oldsize;
 
 	return 0;
 }
@@ -627,7 +630,7 @@ ch_table_grow(const struct ch_type *type
 
 	/* check if the extendible hashing table needs to grow */
 	if (meta->cs_local_level == t->ch_level) {
-		if (ch_table_resize(t) == -1)
+		if (ch_table_resize(type, t) == -1)
 			goto fail;
 	}
 
@@ -720,7 +723,7 @@ _ch_init(const struct ch_type *type, str
 	if (ch_sub_alloc(type, t, &table, &meta) == -1)
 		goto fail;
 
-	if (ch_table_resize(t) == -1)
+	if (ch_table_resize(type, t) == -1)
 		goto fail;
 
 	ch_table_fill(t, 0, table, meta);