From a76f96c951fd24843d2e9df88002f60c044fbcfc Mon Sep 17 00:00:00 2001 From: Gyanu Mayank Date: Tue, 22 Sep 2026 21:19:04 +0530 Subject: [PATCH] Reject a bad subprocess pipe protocol owner with TypeError. The constructor only checked proc and fd under UVLOOP_DEBUG, then cast proc and segfaulted. That check now always runs. Fixes #765. --- tests/test_subprocess_pipe_proto.py | 16 ++++++++++++++++ uvloop/handles/process.pyx | 17 ++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 tests/test_subprocess_pipe_proto.py diff --git a/tests/test_subprocess_pipe_proto.py b/tests/test_subprocess_pipe_proto.py new file mode 100644 index 000000000..d39ceb241 --- /dev/null +++ b/tests/test_subprocess_pipe_proto.py @@ -0,0 +1,16 @@ +import unittest + +from uvloop.loop import ReadSubprocessPipeProto, WriteSubprocessPipeProto + + +class TestSubprocessPipeProto(unittest.TestCase): + def test_rejects_non_process_owner(self): + with self.assertRaises(TypeError): + ReadSubprocessPipeProto(1, 7) + with self.assertRaises(TypeError): + WriteSubprocessPipeProto(1, 7) + + def test_rejects_non_int_fd(self): + # Owner is checked first. A non-process still must not segfault. + with self.assertRaises(TypeError): + WriteSubprocessPipeProto(object(), 'nope') diff --git a/uvloop/handles/process.pyx b/uvloop/handles/process.pyx index 63b982ae5..391390b2d 100644 --- a/uvloop/handles/process.pyx +++ b/uvloop/handles/process.pyx @@ -706,11 +706,18 @@ cdef class UVProcessTransport(UVProcess): class WriteSubprocessPipeProto(aio_BaseProtocol): def __init__(self, proc, fd): - if UVLOOP_DEBUG: - if type(proc) is not UVProcessTransport: - raise TypeError - if not isinstance(fd, int): - raise TypeError + # Release builds used to cast `proc` and segfault. Reject a bad owner + # here so a mistaken constructor argument is a TypeError. + if type(proc) is not UVProcessTransport: + raise TypeError( + 'proc must be a UVProcessTransport, not {!r}'.format( + type(proc).__name__, + ), + ) + if not isinstance(fd, int): + raise TypeError( + 'fd must be an int, not {!r}'.format(type(fd).__name__), + ) self.proc = proc self.fd = fd self.pipe = None