marshal: refuse a back-reference to an object still being written - #8519
Conversation
`w_ref` marks a code or slice entry incomplete until `w_complete`, because the reader rebuilds both from their fields and a `TYPE_REF` issued while those fields are still on the wire names an object that does not exist yet. `WriterRefTable` carries that marker and `write_object_depth` raises `cannot marshal recursion <type> objects` instead of emitting the reference. `test_reference_loop_code`, `test_unmarshallable` and `test_reference_loop_slice` lose their RustPython markers; `test_marshal` is 75 run, 16 skipped. Assisted-by: Claude
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughMarshal serialization now tracks whether referenced objects are incomplete. Recursive references return value errors. Code and slice objects become referenceable after their contents are serialized. ChangesMarshal reference tracking
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: ✨ 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 |
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_marshal.py (TODO: 5) dependencies: dependent tests: (25 tests)
Legend:
|
w_refhanded out a back-reference as soon as an object was registered, so acontainer that reached itself while still being written serialized a
rback-reference to an entry the reader had not finished building.
CPython guards this in
Python/marshal.c:w_refmarks a code or slice entryincomplete when it reserves the index and
w_completeclears the mark once thebody is written; a back-reference taken in between raises
ValueError: cannot marshal recursion %T objects(gh-148653).This mirrors that structure:
WriterRefEntrycarries anincompleteflag.reservesets it for the kinds whose immutable representation cannot berebuilt from a back-reference — code and slice.
try_refreturnsErr(())while the flag is set, whichwrite_object_depthturns into theValueError.completeclears it after the body is written.Three
TODO: RUSTPYTHONmarkers inLib/test/test_marshal.pyare removed:test_unmarshallableskip(panic)test_reference_loop_codeskip(panic)test_reference_loop_sliceexpectedFailuretest_marshalruns 75 tests / 16 skipped (was 18 skipped).Summary by CodeRabbit