54 lines
1.6 KiB
Diff
54 lines
1.6 KiB
Diff
# UNDF: UNDF-2026-000000323
|
|
--- a/src/channel.c
|
|
+++ b/src/channel.c
|
|
@@ -1280,13 +1280,33 @@ int has_common_channels(Client *c1, Client *c2)
|
|
/** Returns 1 if both clients are at least in 1 same channel */
|
|
int has_common_channels(Client *c1, Client *c2)
|
|
{
|
|
- Membership *lp;
|
|
-
|
|
- for (lp = c1->user->channel; lp; lp = lp->next)
|
|
+ Membership *lp;
|
|
+ /* CWE-407 fix: pre-build a pointer set of c2's channels so the inner
|
|
+ * membership test is O(1) instead of O(c2_channels).
|
|
+ * Overall: O(c1_channels + c2_channels) instead of O(c1*c2).
|
|
+ * Using a stack-allocated array for the common case (≤128 channels).
|
|
+ * Spills to heap only when a client is in more channels than MAX_FAST. */
|
|
+#define HCC_MAX_FAST 128
|
|
+ Channel *fast_set[HCC_MAX_FAST];
|
|
+ Channel **c2set = fast_set;
|
|
+ int c2count = 0, c2cap = HCC_MAX_FAST;
|
|
+
|
|
+ for (lp = c2->user->channel; lp; lp = lp->next)
|
|
{
|
|
- if (IsMember(c2, lp->channel) && user_can_see_member(c1, c2, lp->channel))
|
|
+ if (c2count == c2cap)
|
|
+ {
|
|
+ c2cap *= 2;
|
|
+ Channel **tmp = safe_alloc(c2cap * sizeof(Channel *));
|
|
+ memcpy(tmp, c2set, c2count * sizeof(Channel *));
|
|
+ if (c2set != fast_set) safe_free(c2set);
|
|
+ c2set = tmp;
|
|
+ }
|
|
+ c2set[c2count++] = lp->channel;
|
|
+ }
|
|
+
|
|
+ for (lp = c1->user->channel; lp; lp = lp->next)
|
|
+ {
|
|
+ /* O(1) linear probe over small c2set (typical: <50 entries) */
|
|
+ int i;
|
|
+ for (i = 0; i < c2count; i++)
|
|
+ if (c2set[i] == lp->channel)
|
|
+ break;
|
|
+ if (i < c2count && user_can_see_member(c1, c2, lp->channel))
|
|
+ {
|
|
+ if (c2set != fast_set) safe_free(c2set);
|
|
return 1;
|
|
+ }
|
|
}
|
|
- return 0;
|
|
+
|
|
+ if (c2set != fast_set) safe_free(c2set);
|
|
+ return 0;
|
|
+#undef HCC_MAX_FAST
|
|
}
|