Follow CPython's padding rules in a2b_base64 - #8570
Conversation
With strict_mode=True the decoder accepted padding CPython rejects:
>>> binascii.a2b_base64(b'YWJj=', strict_mode=True)
b'abc'
It also dropped data in the default mode, because it returned at the
first pad that completed a quad:
>>> binascii.a2b_base64(b'abc=a')
b'i\xb7' # CPython: b'i\xb7\x1a'
The loop now counts pads and decides at the end, the way CPython does,
so a stray pad is ignored outside strict mode and named as leading,
excess or discontinuous inside it. DecodeError::InvalidPadding was dead
in this file and now carries the excess padding message.
test_base64_strict_mode and test_base64_excess_data were marked as
expected failures and pass now.
Assisted-by: Claude Code:claude-opus-5
|
No actionable comments were generated in the recent review. 🎉 ℹ️ 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)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughBase64 decoding now tracks padding per quartet. Non-strict mode ignores misplaced padding. Strict mode reports distinct leading, excess, discontinuous, and trailing data errors. Final-length validation accounts for padding, and the excess-padding message changed. ChangesBase64 padding validation
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to The PR makes a localized base64 padding behavior correction with targeted tests and reported clean validation; no actionable merge-blocking risk remains beyond normal checks and review. Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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 |
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_binascii.py dependencies: dependent tests: (95 tests)
Legend:
|
Summary
binascii.a2b_base64withstrict_mode=Trueaccepts padding that CPython rejects:The flag exists to reject malformed input, so accepting it silently defeats it.
The same loop also drops data in the default mode. It returns as soon as a pad completes a quad, so whatever follows is lost:
>>> binascii.a2b_base64(b'abc=a') b'i\xb7' # CPython: b'i\xb7\x1a'Both come from the same place. CPython counts pads as it goes and decides at the end; this one decides at the first complete pad sequence and never looks at a pad while
quad_posis still 0. The loop now follows CPython: a pad that fits the current quad is consumed, any other pad is ignored outside strict mode, and strict mode names it leading, excess or discontinuous. The tail reports the two lengths no valid encoding can produce.DecodeError::InvalidPaddingwas mapped toIncorrect padding, but nothing in the file ever built that variant, so it now carriesExcess padding not allowed. The other messages are untouched.Tests
Lib/test/test_binascii.pyalready had both cases, marked as expected failures. They run now:test_base64_strict_mode, which covers all five padding errors across the four buffer typestest_base64_excess_data, whose marker had even recorded the symptom (AssertionError: b'i' != b'i\xb7')What I ran:
cargo run --release -- -m test test_binascii: 93 tests, 17 skipped, SUCCESScargo run --release -- -m test test_base64: 41 tests, SUCCESScargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher --exclude rustpython-capi: 41 test binaries, no failurescargo fmt --check, and clippy with the flags CI uses: both cleanI also ran the inputs above plus the padding cases around them under CPython 3.14 and this build side by side. Every returned value agrees now. Two error strings still differ, both because of the
error decoding base64:prefix that #7993 is already working through, so I left them alone.AI assistance
Claude Code (claude-opus-5) helped with the comparison against CPython, the loop and this description. I read the final diff and ran the checks above on Linux.
Summary by CodeRabbit