java-topology/defects/zeek/unit/ZeekAttributesFindTest.java
russell@unturf.com ba818693db nmap-0002 + haproxy-0004 + nginx-0004 + weechat-0003 + zeek-0002 + curl-0004: 6 new CWE-407 defects in network tools; count 693→699
nmap-0002:     nmap.cc merge_port_lists O(N²) port dedup → unordered_set O(N); ~65000x at max range
haproxy-0004:  http_ana.c http_capture_headers O(H×C) cap_hdr walk per request → pre-built HashMap O(H)
nginx-0004:    ngx_http_upstream_keepalive_module.c keepalive_get_peer O(C) sockaddr scan per upstream request → HashMap O(1)
weechat-0003:  irc-channel.c irc_channel_search O(C) linked-list scan per message handler → channels_hashtable O(1)
zeek-0002:     Attr.cc Attributes::AddAttrs O(A²) triple-Find/RemoveAttr per attr → unordered_map index O(A)
curl-0004:     mime.c search_header O(P×H) 3x per part per mime_add_headers → pre-indexed header name set O(P)
2026-03-29 22:22:11 -04:00

119 lines
4 KiB
Java
Raw 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.

package unit;
import java.util.*;
/**
* zeek-0002 — CWE-407: Attributes::AddAttrs O(A²) during script compilation
*
* Models src/Attr.cc Attributes::AddAttr/AddAttrs/Find/RemoveAttr:
* Slow: attrs stored as std::vector; Find() and RemoveAttr() are O(A) each.
* AddAttr() calls Find + RemoveAttr + Find = 3×O(A).
* AddAttrs(A attrs) → O(A²) total.
* Fast: attrs indexed by tag in HashMap → O(1) Find/Remove per AddAttr.
*
* Trigger: Zeek script compilation of `redef record` with many attributes.
* Large enterprise deployments can have record types with 20-50+ attributes
* redefined across many script files.
*/
public class ZeekAttributesFindTest {
// Simplified AttrTag enum (Zeek has ~40 values)
enum AttrTag {
LOG, OPTIONAL, DEFAULT, REDEF, DEPRECATED, ERROR_HANDLER,
ADD_FUNC, DEL_FUNC, EXPIRE_READ, EXPIRE_WRITE, EXPIRE_CREATE,
EXPIRE_FUNC, TYPE_COLUMN, BROKER_STORE, BACKEND, RAW_OUTPUT,
IS_USED, NO_CPP_OPT, NO_ZAM_OPT, BROKER_STORE_ALLOW_COMPLEX,
A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30;
}
static class Attr {
final AttrTag tag;
Attr(AttrTag tag) { this.tag = tag; }
}
// --- SLOW: vector-based Attributes (defect) ---
static class AttributesSlow {
final List<Attr> attrs = new ArrayList<>();
long ops = 0;
Attr find(AttrTag tag) {
for (Attr a : attrs) { ops++; if (a.tag == tag) return a; }
return null;
}
void removeAttr(AttrTag tag) {
attrs.removeIf(a -> { ops++; return a.tag == tag; });
}
void addAttr(Attr attr) {
find(attr.tag); // O(A) scan #1 - check for dup
removeAttr(attr.tag); // O(A) scan #2 - remove old
attrs.add(attr);
find(AttrTag.REDEF); // O(A) scan #3 - check redef
}
void addAttrs(List<Attr> newAttrs) {
for (Attr a : newAttrs) addAttr(a);
}
}
// --- FAST: map-indexed Attributes (fix) ---
static class AttributesFast {
final Map<AttrTag, Attr> attrMap = new HashMap<>();
final List<Attr> attrs = new ArrayList<>(); // preserved for ordered iteration
long ops = 0;
Attr find(AttrTag tag) {
ops++; // O(1) map lookup
return attrMap.get(tag);
}
void removeAttr(AttrTag tag) {
ops++; // O(1) map remove
if (attrMap.remove(tag) != null)
attrs.removeIf(a -> a.tag == tag);
}
void addAttr(Attr attr) {
find(attr.tag); // O(1) check #1
removeAttr(attr.tag); // O(1) remove
attrs.add(attr);
attrMap.put(attr.tag, attr);
find(AttrTag.REDEF); // O(1) check #2
}
void addAttrs(List<Attr> newAttrs) {
for (Attr a : newAttrs) addAttr(a);
}
}
public static void main(String[] args) {
System.out.println("zeek-0002 CWE-407: Attributes::AddAttrs O(A²) vs O(A)");
System.out.println("=======================================================");
AttrTag[] allTags = AttrTag.values();
for (int A : new int[]{ 10, 20, 30 }) {
// Build list of A attributes to add
List<Attr> toAdd = new ArrayList<>();
for (int i = 0; i < A; i++)
toAdd.add(new Attr(allTags[i % allTags.length]));
// Simulate AddAttrs on a type being redef'd
AttributesSlow slow = new AttributesSlow();
AttributesFast fast = new AttributesFast();
slow.addAttrs(toAdd);
fast.addAttrs(toAdd);
double ratio = (double) slow.ops / fast.ops;
System.out.printf(" A=%2d attributes: slow=%,5d ops fast=%,4d ops speedup=%.1fx%n",
A, slow.ops, fast.ops, ratio);
assert slow.ops > fast.ops * (A / 4) :
"Expected slow > fast*" + (A/4) + " but slow=" + slow.ops + " fast=" + fast.ops;
}
System.out.println("\nPASS");
}
}