2.1 KiB
2.1 KiB
UNDF: UNDF-2026-000000416
hazelcast-0002 — QueueContainer.contains() O(D×Q) nested scan
Classification
| Field | Value |
|---|---|
| CWE | CWE-407: Algorithmic Complexity — Linear Membership Test in Outer Loop |
| Severity | MEDIUM |
| Component | hazelcast/src/main/java/com/hazelcast/collection/impl/queue/QueueContainer.java |
| Method | contains(Collection<Data> dataSet) |
| Lines | 753–767 |
| Public API | IQueue.containsAll(Collection) |
Defective Code
// QueueContainer.java:753-767
public boolean contains(Collection<Data> dataSet) {
for (Data data : dataSet) { // O(D) outer loop
boolean contains = false;
for (QueueItem item : getItemQueue()) { // O(Q) inner scan
if (item.getSerializedObject() != null && item.getSerializedObject().equals(data)) {
contains = true;
break;
}
}
if (!contains) {
return false;
}
}
return true;
}
For each of D query items, the entire Q-item queue is scanned linearly.
Root Cause
No pre-built lookup structure over queue items. Each membership test costs O(Q).
Total cost for containsAll(D items) on a Q-item queue: O(D × Q).
Fix
Build a Set<Data> from the queue's serialized objects once, then check each query
item against the set in O(1).
public boolean contains(Collection<Data> dataSet) {
Set<Data> queueData = new HashSet<>(getItemQueue().size() * 2);
for (QueueItem item : getItemQueue()) {
if (item.getSerializedObject() != null) {
queueData.add(item.getSerializedObject());
}
}
for (Data data : dataSet) { // O(D)
if (!queueData.contains(data)) { // O(1)
return false;
}
}
return true;
}
Complexity
| Before | After | |
|---|---|---|
contains(D items) on Q-item queue |
O(D × Q) | O(Q + D) |
Speedup Estimate
At D = 500, Q = 1 000 (all-distinct, worst case — every item found): ~250× fewer comparisons. At D = 200, Q = 5 000: ~1 000× fewer comparisons.