tonghuaroot · GitHub

Crash report

What happened?

Bug description

Similar to gh-143637, socket.sendmsg() and socket.recvmsg_into() can crash due to re-entrant mutation during argument parsing, but via the __buffer__ protocol instead of __index__.

Affected functions

Function Argument Trigger
sendmsg() arg 1 (data buffers) __buffer__
recvmsg_into() arg 1 (buffers) __buffer__

Root cause

Same as gh-143637: PySequence_Fast() returns the original list when input is already a list. During iteration, PyObject_GetBuffer() triggers __buffer__ callbacks which can clear the list, causing subsequent accesses to read invalid memory.

import socket
seq = []
class MutBuffer:
    def __init__(self, data):
        self._data = bytes(data)
        self.tripped = False
    def __buffer__(self, flags):
        if not self.tripped:
            self.tripped = True
            seq.clear()
        return memoryview(self._data)
seq[:] = [MutBuffer(b'Hello'), b'World', b'Test']
left, right = socket.socketpair()
left.sendmsg(seq)  # CRASH: Exit code 139 (SIGSEGV)

PoC - recvmsg_into() crash

import socket
seq = []
class MutBuffer:
    def __init__(self, data):
        self._data = bytearray(data)
        self.tripped = False
    def __buffer__(self, flags):
        if not self.tripped:
            self.tripped = True
            seq.clear()
        return memoryview(self._data)
seq[:] = [MutBuffer(b'x' * 100), bytearray(100), bytearray(100)]
left, right = socket.socketpair()
left.send(b'Hello World!')
right.recvmsg_into(seq)  # CRASH: Exit code 139 (SIGSEGV)

Fix

Replace PySequence_Fast() with PySequence_Tuple() in sock_sendmsg_iovec() and sock_recvmsg_into().

I have a PR ready.

CPython versions tested on:

main branch (3.15.0a5+)

Operating system and architecture:

macOS 15.0 arm64

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Output from running 'python -VV' on the command line:

No response

Linked PRs

Read the original on github.com ↗