Skip to content

Commit fba20e3

Browse files
committed
correction: retain target alignments
Size the bounded alignment LRU for the full 11-length generic unknown-target window so repeated search phases reuse every alignment without reintroducing unbounded attacker-controlled state. Add a regression proving the full window remains hot.\n\nSecurity: preserves the resource bound from #21 while avoiding cache thrash that can consume the fixed correction deadline.\n\nValidation: test_alignment.py 26 passed; full pytest 863 passed; optimized pytest 863 passed; Ruff, format, mypy, and git diff --check passed.
1 parent 2c356e2 commit fba20e3

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

‎src/codex32/correction.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,9 @@ class _Spec:
250250
1023,
251251
)
252252

253-
# Keep all six standard ms target lengths hot without letting arbitrary HRPs
254-
# create process-lifetime state.
255-
_ALIGNMENT_CACHE_SIZE = 8
253+
# Keep every target length from one generic unknown-length search hot without
254+
# letting arbitrary HRPs create process-lifetime state.
255+
_ALIGNMENT_CACHE_SIZE = 11
256256

257257

258258
def _spec_for_checksum(checksum: _Checksum) -> _Spec:

‎tests/test_alignment.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@ def test_syndrome_alignment_cache_is_bounded_for_untrusted_hrps():
2727
assert info.currsize == _ALIGNMENT_CACHE_SIZE
2828

2929

30+
def test_syndrome_alignment_cache_fits_one_unknown_length_search():
31+
observed = 50
32+
targets = sorted({observed + delta for delta in (*range(-4, 5), -8, 8)})
33+
_syndrome_alignment.cache_clear()
34+
35+
first = [_syndrome_alignment(_SHORT_SPEC, "generic", target) for target in targets]
36+
before = _syndrome_alignment.cache_info()
37+
second = [_syndrome_alignment(_SHORT_SPEC, "generic", target) for target in targets]
38+
after = _syndrome_alignment.cache_info()
39+
40+
assert len(targets) == _ALIGNMENT_CACHE_SIZE
41+
assert all(left is right for left, right in zip(first, second, strict=True))
42+
assert after.misses == before.misses
43+
assert after.hits == before.hits + len(targets)
44+
45+
3046
def test_syndrome_alignment_cache_still_reuses_recent_entries():
3147
_syndrome_alignment.cache_clear()
3248
first = _syndrome_alignment(_SHORT_SPEC, "ms", 45)

0 commit comments

Comments
 (0)