zlib: clear unconsumed_tail when a bounded decompress reaches stream end - #8908
Conversation
When a max_length-bounded Decompress.decompress() call reached the end of the stream, the bytes after the stream went to unused_data, but unconsumed_tail kept the previous call's tail, including input the call had already consumed. A later flush() then moved those stale bytes into unused_data. Empty unconsumed_tail at end of stream, as CPython's save_unconsumed_input() does since gh-158169. CPython releases before that change report the bytes after the stream in unconsumed_tail, so the snippet accepts either value when it runs under CPython. Fixes RustPython#8906 Assisted-by: Claude Code:claude-opus-5-5
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: RustPython/RustPython/.coderabbit.yml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughWhen the stream ends, the decompressor now records bytes after the stream in ChangesZlib decompression tail handling
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Medium Suggested reviewers: Merge Risk: ⚪ Minimal · up to The change addresses the reported decompression-state issue, and the supplied regression coverage checks the affected bounded-decompression and flush behavior. No material merge-blocking risk is established. Architecture SummaryArchitecture risk: 🔵 Low · up to The change affects 2 systems. Changed systems: Architecture concerns Review detailsSystems and components
Before / after behavior
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Choose between the empty slice and the rest of the input in one expression instead of reassigning a mutable binding. Assisted-by: Claude Code:claude-opus-5-5
|
Human review by me:
|
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Merging this PR will not alter performance
Comparing Footnotes
|
The snippet no longer branches on sys.implementation. RustPython and CPython after gh-158169 give an empty tail; CPython before it gives the bytes after the stream. The stale tail of RustPythongh-8906 fails either way. Assisted-by: Claude Code:claude-opus-5-5
Fixes #8906.
When a
max_length-boundedDecompress.decompress()call reaches the end of the stream,unconsumed_tailkept the previous call's tail, including input the call had already consumed, and a laterflush()moved those stale bytes intounused_data.Decompressor::decompress_inner(crates/common/src/compression/zlib.rs) now emptiesunconsumed_tailat end of stream and puts the bytes after the stream inunused_data, as CPython'ssave_unconsumed_input()does since gh-158169 (python/cpython commit 8122ff4818). CPython releases before that change report the bytes after the stream inunconsumed_tail, so the new snippet case accepts either value when it runs under CPython.Tests
stream_end_clears_unconsumed_tail(fails before the change: the tail held 29 stale bytes ending inNEXT).extra_tests/snippets/stdlib_zlib.pywith the reproducer fromzlib.decompressobj:unconsumed_tailkeeps stale input when amax_length-bounded call reaches end of stream #8906.cargo test -p rustpython-common --features zlib: 16 passed.test_zlibunder RustPython: 76 run, 4 skipped, 0 failed, before and after; noexpectedFailuremarker changed.cargo fmt --check, clippy onrustpython-commonwith-Dwarnings, ruff and cspell: clean.AI assistance
This change was written with Claude Code (commit trailer
Assisted-by: Claude Code:claude-opus-5-5). It is opened as a draft until a human has verified it, per the AI policy.🤖 Written by Claude Code (2.1.283) using model claude-opus-5-5
Summary by CodeRabbit
flush()preserves the reported trailing data and input state, keeping decompression results consistent after bounded reads.