wave16: nova/keystone/crystal/dovecot/wireshark CWE-407 patches + unit tests

nova-0001: scheduler/manager.py selected_hosts list → set (273x, CRITICAL)
nova-0002: scheduler/host_manager.py lowered_hosts_to_force list → set (43x, HIGH)
keystone-0001: api/users.py token_roles list → set (32x, HIGH)
crystal-0001: syntax/parser.cr type_vars Array#includes? → Set (25x, CRITICAL)
crystal-0002: semantic/restrictions.cr discarded Array#includes? → Set (5x, CRITICAL)
dovecot-0001: mail-storage-hooks.c array_lsearch → sort+bsearch (4x, HIGH)
wireshark-0001: proto_data.c GSList → wmem_map_t (8x, HIGH)

7 unit tests: 9/9 PASS
This commit is contained in:
russell@unturf.com 2026-03-30 07:33:49 -04:00
parent 291620b115
commit 59ae52c7b4
12 changed files with 724 additions and 177 deletions

View file

@ -0,0 +1,107 @@
import java.util.*;
/**
* CWE-407 unit test for wireshark defect.
*
* wireshark-0001: proto_data.c per-packet proto data GSList O(N) lookup
* p_set_proto_data / p_get_proto_data / p_remove_proto_data each do
* g_slist_find_custom(pinfo->proto_data, ...) O(N) scan over all
* per-packet protocol data entries. Called repeatedly per dissector layer.
*
* Fix: replace GSList with wmem_map_t keyed by (proto<<32 | key) O(1).
*/
public class WiresharkTest {
// Simulate GSList-based proto_data (defect)
static class ProtoDataList {
private final List<long[]> entries = new ArrayList<>(); // [proto, key, data_id]
void set(int proto, long key, long data) {
long compKey = ((long) proto << 32) | (key & 0xFFFFFFFFL);
for (long[] e : entries) { // O(N) scan
if (e[0] == compKey) { e[1] = data; return; }
}
entries.add(new long[]{compKey, data});
}
long get(int proto, long key) {
long compKey = ((long) proto << 32) | (key & 0xFFFFFFFFL);
for (long[] e : entries) { // O(N) scan
if (e[0] == compKey) return e[1];
}
return -1;
}
}
// Simulate wmem_map_t-based proto_data (fix)
static class ProtoDataMap {
private final Map<Long, Long> map = new HashMap<>();
void set(int proto, long key, long data) {
map.put(((long) proto << 32) | (key & 0xFFFFFFFFL), data);
}
long get(int proto, long key) {
Long v = map.get(((long) proto << 32) | (key & 0xFFFFFFFFL));
return v != null ? v : -1;
}
}
static void testWireshark0001() throws Exception {
int N = 300; // dissector layers per packet (complex capture)
int PROTOS = 50;
Random rng = new Random(42);
// build test data: N (proto, key, value) tuples
int[][] queries = new int[N][2];
for (int i = 0; i < N; i++) {
queries[i][0] = rng.nextInt(PROTOS);
queries[i][1] = rng.nextInt(1000);
}
// correctness: both implementations return same values after inserts
ProtoDataList plist = new ProtoDataList();
ProtoDataMap pmap = new ProtoDataMap();
for (int i = 0; i < N; i++) {
plist.set(queries[i][0], queries[i][1], i);
pmap.set(queries[i][0], queries[i][1], i);
}
for (int i = 0; i < N; i++) {
long vlist = plist.get(queries[i][0], queries[i][1]);
long vmap = pmap.get(queries[i][0], queries[i][1]);
assert vlist == vmap : "mismatch at " + i + ": " + vlist + " vs " + vmap;
}
// performance: simulate per-packet dissection build once, many repeated lookups
// (dissectors call p_get_proto_data repeatedly on the same pinfo per packet)
long t0 = System.nanoTime();
for (int pkt = 0; pkt < 200; pkt++) {
ProtoDataList pd = new ProtoDataList();
for (int i = 0; i < N; i++) pd.set(queries[i][0], queries[i][1], i);
// simulate many get calls on a fully-populated list (N entries each get is O(N/2))
for (int rep = 0; rep < 50; rep++)
for (int i = 0; i < N; i++) pd.get(queries[i][0], queries[i][1]);
}
long tList = System.nanoTime() - t0;
t0 = System.nanoTime();
for (int pkt = 0; pkt < 200; pkt++) {
ProtoDataMap pd = new ProtoDataMap();
for (int i = 0; i < N; i++) pd.set(queries[i][0], queries[i][1], i);
for (int rep = 0; rep < 50; rep++)
for (int i = 0; i < N; i++) pd.get(queries[i][0], queries[i][1]);
}
long tMap = System.nanoTime() - t0;
double ratio = (double) tList / tMap;
System.out.printf("wireshark-0001: list=%.3fs map=%.3fs ratio=%.1f×%n",
tList / 1e9, tMap / 1e9, ratio);
assert ratio > 5 : "Expected >5× speedup, got " + ratio;
System.out.println("PASS wireshark-0001");
}
public static void main(String[] args) throws Exception {
testWireshark0001();
System.out.println("ALL PASS");
}
}