Commit 3674873f4 for clamav.net

commit 3674873f45ff942b2b92313dd14a01dc267bcf12
Author: sharkautarch <128002472+sharkautarch@users.noreply.github.com>
Date:   Mon May 4 18:00:37 2026 -0400

    ClamOnAcc: Fix hash bucket list corruption on collision (#1712)

    When onas_ht_insert() adds an element whose hash maps to an existing
    bucket, the bucket is already part of the activated-bucket list. The old
    code appended that same bucket to the list again, resetting bckt->next to
    NULL and making any following buckets unreachable from ht->head.

    OnAccessExcludePath walks the activated-bucket list when removing watched
    paths. If a collision corrupts that list, some active directories can be
    skipped and remain watched.

    Track whether onas_ht_insert() allocated a new bucket, and only link the
    bucket into ht->head/ht->tail when it is new. Colliding elements are still
    inserted into the existing bucket without changing the bucket list.

diff --git a/clamonacc/inotif/hash.c b/clamonacc/inotif/hash.c
index e438f0471..a82d82d43 100644
--- a/clamonacc/inotif/hash.c
+++ b/clamonacc/inotif/hash.c
@@ -254,10 +254,12 @@ int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem)
     int idx                  = onas_hash(elem->key, elem->klen, ht->size);
     struct onas_bucket *bckt = ht->htable[idx];

-    int ret        = 0;
-    uint32_t bsize = 0;
+    int ret          = 0;
+    uint32_t bsize   = 0;
+    bool bckt_is_new = false;

     if (bckt == NULL) {
+        bckt_is_new     = true;
         ht->htable[idx] = onas_bucket_init();
         if (ht->htable[idx] == NULL) return CL_EMEM;

@@ -270,7 +272,7 @@ int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem)
         ht->tail   = bckt;
         bckt->prev = NULL;
         bckt->next = NULL;
-    } else {
+    } else if (bckt_is_new) { // bckts are never removed from the linked list
         struct onas_bucket *ht_tail = ht->tail;
         ht_tail->next               = bckt;
         bckt->prev                  = ht_tail;