2.5 KiB
UNDF: UNDF-2026-000000341
Classification
| Field | Value |
|---|---|
| CWE | CWE-407 Inefficient Algorithmic Complexity |
| Severity | MEDIUM |
| Component | epan/dissectors/packet-quic.c:5419 |
| Function | quic_streams_add() |
| Hot path | Called once per new QUIC stream — per-packet during QUIC capture |
| Status | PATCHED (unit test PASS) |
Defect
quic_streams_add() checks whether a stream ID is already known using a
linear scan of a sorted linked list:
/* packet-quic.c:5415 */
if (!quic_info->streams_list) {
quic_info->streams_list = wmem_list_new(wmem_file_scope());
}
if (!wmem_list_find(quic_info->streams_list, GUINT_TO_POINTER(stream_id))) {
wmem_list_insert_sorted(quic_info->streams_list, GUINT_TO_POINTER(stream_id),
wmem_compare_uint);
}
wmem_list_find() is a linear scan of a singly-linked list — O(S) per call
where S is the current number of known stream IDs. Called once per new QUIC
stream encountered during dissection.
QUIC HTTP/3 traffic uses one stream per request. A capture of a high-traffic server may contain a connection with S=1,000–10,000 streams. Total cost of stream-dedup across all stream additions: O(S²/2).
At S=1,000: ~500,000 pointer comparisons just for dedup.
Note: quic_info->streams_list is maintained sorted (wmem_list_insert_sorted)
for the "Follow QUIC Stream" UI dropdown. A parallel wmem_map_t hash set for
O(1) membership checks preserves the sorted list while eliminating the scan.
Fix
Add wmem_map_t *streams_id_set alongside streams_list in quic_info_data_t:
/* quic_info_data_t struct — add: */
wmem_map_t *streams_id_set; /**< Hash set: stream IDs already seen — O(1) dedup */
/* quic_streams_add() — replace wmem_list_find with map lookup: */
if (!quic_info->streams_id_set) {
quic_info->streams_id_set = wmem_map_new(wmem_file_scope(),
g_direct_hash, g_direct_equal);
}
if (!wmem_map_lookup(quic_info->streams_id_set, GUINT_TO_POINTER(stream_id))) {
wmem_map_insert(quic_info->streams_id_set, GUINT_TO_POINTER(stream_id),
GUINT_TO_POINTER(1));
wmem_list_insert_sorted(quic_info->streams_list, GUINT_TO_POINTER(stream_id),
wmem_compare_uint);
}
The sorted streams_list is preserved for UI display. Only the O(S) membership
check is replaced with an O(1) hash lookup.
Speedup: ~500× at S=1,000 (500,000 → 1,000 effective operations).