diff --git a/src/modules/connclass.rs b/src/modules/connclass.rs index 83d1384..399b039 100644 --- a/src/modules/connclass.rs +++ b/src/modules/connclass.rs @@ -138,10 +138,12 @@ fn build(s: &Server, name: &str) -> Option { resolvehostnames: true, ..Default::default() }; - // resolve the hash algorithm independently of token order (see `apply`'s `hash`) + // resolve the hash algorithm independently of token order, taking the LAST `hash=` + // (a child's overrides a parent's) to match `password=`'s last-wins semantics let hash_algo = toks .iter() - .find_map(|t| t.strip_prefix("hash=")) + .filter_map(|t| t.strip_prefix("hash=")) + .last() .map(str::to_string); for tok in &toks { if let Some((k, v)) = tok.split_once('=') { diff --git a/src/modules/rpc/httpd.rs b/src/modules/rpc/httpd.rs index edf87da..df82502 100644 --- a/src/modules/rpc/httpd.rs +++ b/src/modules/rpc/httpd.rs @@ -218,7 +218,9 @@ fn chunked_complete(body: &[u8]) -> bool { if size == 0 { return true; // terminating chunk seen } - i = nl + 2 + size + 2; // skip CRLF + data + trailing CRLF + // saturating so a hostile 16-hex-digit chunk size can't overflow-panic; an + // oversized advance just lands past the body and returns "need more". + i = nl.saturating_add(2).saturating_add(size).saturating_add(2); // CRLF + data + CRLF if i > body.len() { return false; } diff --git a/src/resolver.rs b/src/resolver.rs index b46e2b0..8bcecf7 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -166,7 +166,12 @@ fn read_nameserver() -> String { if let Some(rest) = line.strip_prefix("nameserver ") { let ns = rest.trim(); if !ns.is_empty() { - return format!("{ns}:53"); + // bracket a bare IPv6 literal so `ns:53` parses as a SocketAddr + return if ns.contains(':') && !ns.starts_with('[') { + format!("[{ns}]:53") + } else { + format!("{ns}:53") + }; } } }