From a1702eede8670a7000cf7e641336eeef4d5909d1 Mon Sep 17 00:00:00 2001 From: disqualifier Date: Mon, 6 Jul 2026 19:21:14 -0400 Subject: [PATCH] fix: stable_id rejects an empty call; hosts(limit=0) returns [] stable_id() with no parts skipped the per-part loop and returned a constant sha256(b''), colliding on every empty call - now raises ValueError like the other weak-id guards. hosts(cidr, limit=0) checked the cap after appending, so limit=0 yielded one host - move the check before the append so limit=0 returns []. Signed-off-by: disqualifier --- src/commons/addr/ip.py | 2 +- src/commons/masking.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/commons/addr/ip.py b/src/commons/addr/ip.py index 2aabe08..a95488e 100644 --- a/src/commons/addr/ip.py +++ b/src/commons/addr/ip.py @@ -115,7 +115,7 @@ def hosts(cidr: str, *, limit: Optional[int] = None) -> List[str]: gen = ipaddress.ip_network(cidr, strict=False).hosts() out: List[str] = [] for host in gen: - out.append(str(host)) if limit is not None and len(out) >= limit: break + out.append(str(host)) return out diff --git a/src/commons/masking.py b/src/commons/masking.py index b06ab68..3d8b292 100644 --- a/src/commons/masking.py +++ b/src/commons/masking.py @@ -119,11 +119,14 @@ def stable_id(*parts: str, length: int = 16) -> str: """deterministic id from ordered parts; same inputs always produce the same id joins the parts with a ``\\x00`` separator (so ``("ab","c")`` != ``("a","bc")``) and - returns the leading ``length`` hex chars of their sha256. raises ValueError on an empty - part, a non-str part, or a non-positive length - fail loud rather than emit a weak id. + returns the leading ``length`` hex chars of their sha256. raises ValueError on no parts, + an empty part, a non-str part, or a non-positive length - fail loud rather than emit a + weak or constant id. """ if length <= 0: raise ValueError(f"stable_id: length must be positive, got {length}") + if not parts: + raise ValueError("stable_id: needs at least one part") for part in parts: if not isinstance(part, str): raise ValueError(f"stable_id: parts must be str, got {type(part).__name__}")