stamparm/maltrail · error
aho-corasick build
Error message
aho-corasick build
What it means
The settings module builds Aho-Corasick automata for pre-condition pattern matching via ac(), which panics with "aho-corasick build" if AhoCorasick::new(patterns) returns an Err. The aho-corasick library only fails construction in rare cases (e.g. the match kind or pattern set is not representable, or pattern limits are exceeded), so this expect is an internal-invariant assertion: Statics::build cannot proceed without the automaton.
Solutions
- Inspect the pattern constants passed to ac() (SUSPICIOUS_HTTP_REQUEST_PRE_CONDITION etc.) for entries incompatible with the builder configuration
- Print/return the underlying aho_corasick::Error instead of expect to see the real cause
- Pin or update the aho-corasick dependency to a version compatible with the pattern set
- If an empty pattern list is legitimate, construct with AhoCorasickBuilder and handle the empty case explicitly
Example fix
// before
fn ac(patterns: &[&str]) -> AhoCorasick {
AhoCorasick::new(patterns).expect("aho-corasick build")
}
// after
fn ac(patterns: &[&str]) -> AhoCorasick {
AhoCorasick::new(patterns).unwrap_or_else(|e| panic!("aho-corasick build failed for {:?}: {e}", patterns))
} Defensive patterns
Strategy: validation
Validate before calling
assert!(!patterns.is_empty(), "ac() pattern list must not be empty");
Type guard
fn valid_patterns(patterns: &[&str]) -> bool { !patterns.is_empty() && patterns.iter().all(|p| !p.is_empty()) } Try / catch
let automaton = AhoCorasick::new(patterns).unwrap_or_else(|e| panic!("aho-corasick build: {e}")); Prevention
- Keep pattern constants non-empty and reviewed
- Pin aho-corasick versions and read changelogs before upgrading
- Return the underlying error in panic messages for diagnosability
When it happens
Trigger: Statics::build() calls ac(SUSPICIOUS_HTTP_REQUEST_PRE_CONDITION), ac(SUSPICIOUS_PROXY_PROBE_PRE_CONDITION), ac(WHITELIST_HTTP_REQUEST_PATHS) or ac(WHITELIST_DIRECT_DOWNLOAD_KEYWORDS) and AhoCorasick::new returns Err (empty/invalid pattern configuration or aho-corasick build limitation for the given MatchKind).
Common situations: Shipping a pattern list constant that is malformed for the builder configuration; upgrading aho-corasick to a version with stricter construction rules; accidentally passing an empty slice where the automaton kind requires patterns.
Related errors
- settings::init() must run before statics()
- forwarded-for regex
- one of the two matched
- just probed
- SUSPICIOUS_HTTP_REQUEST_REGEXES must carry a 'code…
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/6de3b8d744f89be1.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/settings.rs:243
/// `\A\d+\-\d+\-\d+\-\d+\Z`, hand-coded — the dashed-quad first label check.
#[inline]
pub fn is_dashed_quad(label: &str) -> bool {
let mut groups = 0;
for part in label.split('-') {
if part.is_empty() || !part.bytes().all(|c| c.is_ascii_digit()) {
return false;
}
groups += 1;
}
groups == 4
}
pub fn statics() -> &'static Statics {
STATICS.get().expect("settings::init() must run before statics()")
}
fn ac(patterns: &[&str]) -> AhoCorasick {
AhoCorasick::new(patterns).expect("aho-corasick build")
}
/// `ac()` for patterns that have to match regardless of case, which is how HTTP header names
/// arrive on the wire.
fn ac_nocase(patterns: &[&str]) -> AhoCorasick {
aho_corasick::AhoCorasickBuilder::new().ascii_case_insensitive(true).build(patterns).expect("aho-corasick build")
}
impl Statics {
pub fn build(root: PathBuf) -> Statics {
let ua_src = build_suspicious_ua_regex(&root);
let suspicious_ua = match pyre::build(&ua_src) {
Ok(re) => Some(re),
Err(e) => {
crate::ceprintln!("[!] unable to compile SUSPICIOUS_UA_REGEX ({e}); user-agent heuristic disabled");
None
}
};View on GitHub (pinned to 77cfb06d76)