Skip to content

fix: bound QuestionHistory size to prevent LAN-driven OOM#1733

Draft
bluetoothbot wants to merge 1 commit into
python-zeroconf:masterfrom
bluetoothbot:koan/fix-issue-1723
Draft

fix: bound QuestionHistory size to prevent LAN-driven OOM#1733
bluetoothbot wants to merge 1 commit into
python-zeroconf:masterfrom
bluetoothbot:koan/fix-issue-1723

Conversation

@bluetoothbot
Copy link
Copy Markdown
Contributor

@bluetoothbot bluetoothbot commented May 18, 2026

Summary

QuestionHistory._history was unbounded between the periodic 10s async_expire ticks driven by _CACHE_CLEANUP_INTERVAL. A LAN peer streaming distinct questions could grow the dict (and the retained known_answers sets) for ~10s before the next cleanup, easily reaching hundreds of MB at line-rate.

Cap _history at a configurable upper bound, with opportunistic expiry on insert and oldest-first FIFO eviction as a fallback. Mirrors the _MAX_CACHE_RECORDS pattern from #1718.

Fixes #1723

Changes

  • Add _MAX_QUESTION_HISTORY_ENTRIES = 10000 to const.py.
  • In QuestionHistory.add_question_at_time, when the cap would be exceeded by a new entry, first call async_expire(now) to drop entries past _DUPLICATE_QUESTION_INTERVAL; if still full, evict the oldest insertion (Python dict preserves insertion order) until there is room.
  • Update _history.pxd to declare the new constant for the Cython hot path.

Test plan

  • New tests/test_history.py cases:
    • test_question_history_bounded — flooding past the cap keeps _history size ≤ cap.
    • test_question_history_evicts_oldest_first — earliest-inserted entry is the first dropped at cap.
    • test_question_history_opportunistic_expire — stale entries are reclaimed before fresh ones are evicted.
  • Existing suppression + expiry tests still pass.
  • SKIP_CYTHON=1 poetry run pytest --timeout=60 tests → 361 passed, 2 skipped.
  • poetry run cython -3 src/zeroconf/_history.py compiles cleanly with the updated .pxd.

Generated by Kōan /fix


Quality Report

Changes: 4 files changed, 70 insertions(+), 1 deletion(-)

Code scan: clean

Tests: passed (4 PASSED)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

QuestionHistory._history was unbounded between the 10s cache-cleanup
ticks. A LAN peer streaming distinct questions could grow the dict
(and the retained known_answers sets) for ~10s before async_expire
ran, easily reaching hundreds of MB at line-rate.

Cap _history at _MAX_QUESTION_HISTORY_ENTRIES (10000). When the cap
is hit on insert, first call async_expire(now) opportunistically to
drop entries past _DUPLICATE_QUESTION_INTERVAL; if the dict is still
full, evict the oldest insertion (dict is ordered) until there is
room. Match the existing DNSCache cap pattern.

Fixes python-zeroconf#1723
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.76%. Comparing base (31194a3) to head (1998e43).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1733   +/-   ##
=======================================
  Coverage   99.76%   99.76%           
=======================================
  Files          33       33           
  Lines        3440     3446    +6     
  Branches      473      475    +2     
=======================================
+ Hits         3432     3438    +6     
  Misses          5        5           
  Partials        3        3           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 18, 2026

Merging this PR will not alter performance

✅ 11 untouched benchmarks


Comparing bluetoothbot:koan/fix-issue-1723 (1998e43) with master (31194a3)

Open in CodSpeed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security: QuestionHistory grows unbounded between 10s cleanup ticks under a question flood

1 participant