comms/voip/smtp: 30 CWE-407 defects + 9 CLEAN; 224 sites, 101 ecosystems

This commit is contained in:
russell@unturf.com 2026-03-27 14:37:02 -04:00
parent 4d3fcc8e73
commit b3842ab6b8
86 changed files with 6516 additions and 5 deletions

View file

@ -0,0 +1,201 @@
package unit;
import java.util.*;
/**
* PostfixTest — CWE-407 benchmarks for postfix-0001 and postfix-0002
*
* postfix-0001: resolve_addr() calls string_list_match(virt_alias_doms/relay_domains)
* O(K) per RCPT-TO, O(K×M) total for M recipients.
* Fix: pre-build HashMap from inline domain patterns → O(M).
*
* postfix-0002: cleanup_masquerade_external() calls string_list_match(masq_exceptions)
* O(E) per message address, O(N×E) total for N addresses.
* Fix: pre-build HashMap from exceptions → O(N).
*
* Run: javac -d . PostfixTest.java && java -ea unit.PostfixTest
*/
public class PostfixTest {
// ── Shared bench harness ──────────────────────────────────────────────────
static void bench(String label, Runnable slow, Runnable fast, long sOps, long fOps) {
slow.run(); fast.run(); // warm-up
long t0 = System.nanoTime(); slow.run(); long sMs = (System.nanoTime() - t0) / 1_000_000;
long t1 = System.nanoTime(); fast.run(); long fMs = (System.nanoTime() - t1) / 1_000_000;
double r = fOps > 0 ? (double) sOps / fOps : 0;
System.out.printf(" %-56s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.0fx%n",
label, sMs, sOps, fMs, fOps, r);
}
// ── postfix-0001: resolve_addr() domain list scan ─────────────────────────
/**
* SLOW: string_list_match — iterate ARGV<String> of K inline domain patterns
* for each of M recipient domains. Models the Postfix ARGV-based match_list.
*
* Returns the exact number of strcmp operations performed.
*/
static long resolveSlow(int domainPatterns, int recipients) {
// Build ARGV-equivalent: list of domain strings
List<String> argv = new ArrayList<>(domainPatterns);
for (int i = 0; i < domainPatterns; i++) argv.add("hosted-" + i + ".example.com");
long ops = 0;
for (int rcpt = 0; rcpt < recipients; rcpt++) {
// Each rcpt is from a different domain; worst-case: not in list
String domain = "sender-" + rcpt + ".example.com";
// match_list_match: linear scan of ARGV
for (String pat : argv) {
ops++;
if (pat.equalsIgnoreCase(domain)) break;
}
}
return ops;
}
/**
* FAST: HashMap lookup — O(1) per recipient domain.
* Models the patched string_cache HTABLE inside match_list_match.
*/
static long resolveFast(int domainPatterns, int recipients) {
// Build hash map from inline patterns
Set<String> hashCache = new HashSet<>(domainPatterns * 2);
for (int i = 0; i < domainPatterns; i++) hashCache.add("hosted-" + i + ".example.com");
long ops = 0;
for (int rcpt = 0; rcpt < recipients; rcpt++) {
String domain = "sender-" + rcpt + ".example.com";
ops++; // O(1) hash lookup
hashCache.contains(domain);
}
return ops;
}
// ── postfix-0002: cleanup_masquerade_external() exception scan ────────────
/**
* SLOW: string_list_match(masq_exceptions, username) — O(E) scan per address.
* Models the ARGV iteration in cleanup_masquerade_external().
*/
static long masqExceptionSlow(int exceptions, int addresses) {
List<String> exceptionList = new ArrayList<>(exceptions);
for (int i = 0; i < exceptions; i++) exceptionList.add("root" + i);
long ops = 0;
for (int addr = 0; addr < addresses; addr++) {
// Each address has a unique username; worst-case: not in exceptions
String username = "user" + addr;
for (String exc : exceptionList) {
ops++;
if (exc.equalsIgnoreCase(username)) break;
}
}
return ops;
}
/**
* FAST: HashMap lookup for masquerade exceptions — O(1) per address.
* Models the patched htable_find() in cleanup_masquerade_external().
*/
static long masqExceptionFast(int exceptions, int addresses) {
Set<String> exceptionSet = new HashSet<>(exceptions * 2);
for (int i = 0; i < exceptions; i++) exceptionSet.add("root" + i);
long ops = 0;
for (int addr = 0; addr < addresses; addr++) {
String username = "user" + addr;
ops++; // O(1) hash lookup
exceptionSet.contains(username);
}
return ops;
}
/**
* SLOW: masquerade domain ARGV scan — O(D) per address.
* Models the for (masqp = masq_domains->argv; ...) loop in
* cleanup_masquerade_external().
*/
static long masqDomainSlow(int masqDomains, int addresses) {
List<String> domainList = new ArrayList<>(masqDomains);
for (int i = 0; i < masqDomains; i++) domainList.add("corp" + i + ".example.com");
long ops = 0;
for (int addr = 0; addr < addresses; addr++) {
// Address is in a sub-domain of one of the masq domains (find last match)
String addrDomain = "mail.corp" + (addr % masqDomains) + ".example.com";
for (String masq : domainList) {
ops++;
if (addrDomain.endsWith("." + masq) || addrDomain.equals(masq)) break;
}
}
return ops;
}
/**
* FAST: HashMap for exact-match masquerade domains — O(1) per address.
* Models the htable_find(masq_domain_cache, domain) fast path.
*/
static long masqDomainFast(int masqDomains, int addresses) {
Map<String, String> domainMap = new HashMap<>(masqDomains * 2);
for (int i = 0; i < masqDomains; i++) {
String d = "corp" + i + ".example.com";
domainMap.put(d, d);
}
long ops = 0;
for (int addr = 0; addr < addresses; addr++) {
String addrDomain = "mail.corp" + (addr % masqDomains) + ".example.com";
ops++; // O(1) hash lookup (exact parent domain)
// Real patch also handles subdomain stripping, but lookup is O(1)
domainMap.containsKey(addrDomain);
}
return ops;
}
// ── main ──────────────────────────────────────────────────────────────────
public static void main(String[] args) {
final int K = 500; // inline domain patterns in virt_alias/relay_domains
final int M = 2000; // recipients per mailing-list message
final int E = 200; // masquerade_exceptions entries
final int N = 1000; // header addresses in a large message
final int D = 100; // masquerade_domains entries
System.out.println("PostfixTest — CWE-407");
System.out.println();
System.out.println("postfix-0001: resolve_addr() domain list scan");
final long[] sOps1 = new long[1], fOps1 = new long[1];
bench(String.format("resolve K=%d patterns, M=%d recipients", K, M),
() -> { sOps1[0] = resolveSlow(K, M); },
() -> { fOps1[0] = resolveFast(K, M); },
resolveSlow(K, M), resolveFast(K, M));
assert sOps1[0] > fOps1[0] * 100 :
"postfix-0001: expected >100x more ops slow vs fast";
System.out.println();
System.out.println("postfix-0002: cleanup_masquerade_external() scans");
final long[] sOps2 = new long[1], fOps2 = new long[1];
bench(String.format("masq-exceptions E=%d, N=%d addresses", E, N),
() -> { sOps2[0] = masqExceptionSlow(E, N); },
() -> { fOps2[0] = masqExceptionFast(E, N); },
masqExceptionSlow(E, N), masqExceptionFast(E, N));
assert sOps2[0] > fOps2[0] * 50 :
"postfix-0002a: expected >50x more ops slow vs fast";
final long[] sOps3 = new long[1], fOps3 = new long[1];
bench(String.format("masq-domains D=%d, N=%d addresses", D, N),
() -> { sOps3[0] = masqDomainSlow(D, N); },
() -> { fOps3[0] = masqDomainFast(D, N); },
masqDomainSlow(D, N), masqDomainFast(D, N));
assert sOps3[0] > fOps3[0] * 10 :
"postfix-0002b: expected >10x more ops slow vs fast";
System.out.println();
System.out.println("All assertions passed.");
}
}