comms/voip/smtp: 30 CWE-407 defects + 9 CLEAN; 224 sites, 101 ecosystems
This commit is contained in:
parent
4d3fcc8e73
commit
b3842ab6b8
86 changed files with 6516 additions and 5 deletions
201
defects/postfix/unit/PostfixTest.java
Normal file
201
defects/postfix/unit/PostfixTest.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue