java-topology/defects/zabbix-0002/test/ZabbixDiscovererQueueDedupTest.java
russell@unturf.com 0de158cd7a monitoring scan: nagioscore 2 defects, zabbix 2 defects, zenoss CLEAN
nagioscore-0001: add_notification find_notification linked-list O(C²) HIGH 999x
nagioscore-0002: add_object_to_objectlist linked-list dedup O(N²) MEDIUM 1499x
zabbix-0001: process_problem_tags tag dedup O(T²) HIGH 1499x
zabbix-0002: discoverer_queue_lock job ID dedup O(N²) MEDIUM 1499x
zenoss: CLEAN — uses OrderedDict/set/catalog throughout

4/4 PASS, 4 defects across 2 targets
2026-03-30 16:56:56 -04:00

76 lines
2.8 KiB
Java
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import java.util.*;
/**
* CWE-407 unit test for Zabbix zabbix-0002:
* discoverer_queue_lock() in discoverer_queue.c — O(N²) job ID dedup via
* zbx_vector_uint64_search linear scan.
*
* Defect: While iterating discovery jobs in the queue, the code builds a
* visited-IDs vector using zbx_vector_uint64_search (linear scan) to detect
* when we've looped back to a previously-seen job. N jobs × O(N) search = O(N²).
*
* Fix: Use a HashSet (zbx_hashset_t in C) for O(1) ID membership check.
*/
public class ZabbixDiscovererQueueDedupTest {
public static void main(String[] args) {
int N = 3000; // number of discovery jobs in queue
// Simulate unique job IDs
long[] jobIds = new long[N];
for (int i = 0; i < N; i++) {
jobIds[i] = i + 1;
}
// --- Defective: linear scan of ids vector ---
List<Long> idsDefective = new ArrayList<>();
long opsDefective = 0;
long startDef = System.nanoTime();
for (long id : jobIds) {
boolean found = false;
for (Long existing : idsDefective) {
opsDefective++;
if (existing == id) {
found = true;
break;
}
}
if (!found) {
idsDefective.add(id);
}
}
long defectiveNs = System.nanoTime() - startDef;
// --- Fixed: HashSet for O(1) lookup ---
HashSet<Long> idsFixed = new HashSet<>();
long opsFixed = 0;
long startFix = System.nanoTime();
for (long id : jobIds) {
opsFixed++;
if (!idsFixed.contains(id)) {
idsFixed.add(id);
}
}
long fixedNs = System.nanoTime() - startFix;
double ratio = (double) opsDefective / Math.max(opsFixed, 1);
double speedup = (double) defectiveNs / Math.max(fixedNs, 1);
System.out.println("=== Zabbix zabbix-0002: discoverer queue ID dedup CWE-407 ===");
System.out.println("Jobs: " + N);
System.out.println("Defective ops: " + opsDefective);
System.out.println("Fixed ops: " + opsFixed);
System.out.println("Op ratio: " + String.format("%.1fx", ratio));
System.out.println("Defective time: " + (defectiveNs / 1_000_000) + " ms");
System.out.println("Fixed time: " + (fixedNs / 1_000_000) + " ms");
System.out.println("Speedup: " + String.format("%.1fx", speedup));
assert idsFixed.size() == N : "Fixed should have all IDs";
assert idsDefective.size() == N : "Defective should have all IDs";
boolean pass = ratio > 5.0;
System.out.println("RESULT: " + (pass ? "PASS" : "FAIL") +
" (ratio " + String.format("%.1f", ratio) + "x, threshold 5x)");
if (!pass) System.exit(1);
}
}