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)
This commit is contained in:
russell@unturf.com 2026-03-29 22:22:11 -04:00
parent 421f3352c7
commit ba818693db
21 changed files with 2213 additions and 0 deletions

View file

@ -0,0 +1,119 @@
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");
}
}