Skip to content

Fix out-of-bounds read on non-contiguous memoryview in pack_command - #252

Open
Usamak06 wants to merge 1 commit into
redis:masterfrom
Usamak06:pack-memoryview-contiguity
Open

Usamak06 wants to merge 1 commit into
redis:masterfrom
Usamak06:pack-memoryview-contiguity

Conversation

@Usamak06

@Usamak06 Usamak06 commented Oct 7, 2026 •

Copy link
Copy Markdown

pack_command copies p_buf->len bytes from the base pointer PyMemoryView_GET_BUFFER returns, which only spans the payload when the view is C-contiguous; a reversed or strided memoryview puts buf at a different offset and carries its own strides, so the copy runs off the end of the underlying buffer and the out-of-bounds bytes end up in the packed command. Packing memoryview(bytearray(b'.' * 32))[::-1] returns 15 bytes belonging to the next heap allocation, and a 256 MiB bytearray segfaults. Acquiring the view with PyObject_GetBuffer under PyBUF_SIMPLE rejects non-contiguous input with the same BufferError that Reader.feed already raises for it and leaves contiguous memoryviews unchanged; the added test fails before the change, and the suite passes on CPython 3.11 and PyPy 3.11 with and without NDEBUG.


Note

High Risk
Fixes a memory-safety bug (OOB read / possible segfault and leaking adjacent heap bytes into packed commands) in command serialization.

Overview
Fixes an out-of-bounds read when pack_command packs a non-contiguous memoryview (e.g. reversed or strided). The old path used PyMemoryView_GET_BUFFER and copied len bytes from buf as if the view were C-contiguous, which could read past the underlying buffer and put garbage (or crash) into the serialized Redis command.

Memoryview arguments are now acquired via PyObject_GetBuffer(..., PyBUF_SIMPLE) with error handling and PyBuffer_Release, so non-contiguous views raise BufferError instead of being packed incorrectly. Contiguous memoryviews behave as before.

A regression test packs a reversed memoryview and expects BufferError.

Reviewed by Cursor Bugbot for commit 216061c. Bugbot is set up for automated code reviews on this repo. Configure here.

The memoryview branch copied p_buf->len bytes from the base pointer of
PyMemoryView_GET_BUFFER, which only spans the payload when the view is
C-contiguous. A reversed or strided view puts buf at a different offset
and carries its own strides, so the copy ran off the end of the
underlying buffer and the out-of-bounds bytes were spliced into the
packed command: packing memoryview(bytearray(b'.' * 32))[::-1] returned
15 bytes of the next heap allocation, and a 256 MiB bytearray
segfaulted. Acquiring the view with PyObject_GetBuffer under
PyBUF_SIMPLE rejects non-contiguous input with the same BufferError
that Reader.feed already raises for it, and leaves contiguous
memoryviews unchanged.
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.

1 participant