apply bpo-37228

* refs python/cpython#17311
This commit is contained in:
Fantix King 2020-05-09 14:50:43 -05:00
parent 9e017e6ee9
commit 506a2aa1eb
5 changed files with 62 additions and 16 deletions

View File

@ -328,6 +328,47 @@ class _TestUDP:
tr.close()
self.loop.run_until_complete(pr.done)
def _skip_create_datagram_endpoint_reuse_addr(self):
if self.implementation == 'asyncio':
if sys.version_info[:2] >= (3, 11):
raise unittest.SkipTest()
if (3, 8, 0) <= sys.version_info < (3, 8, 1):
raise unittest.SkipTest()
if (3, 7, 0) <= sys.version_info < (3, 7, 6):
raise unittest.SkipTest()
if sys.version_info < (3, 6, 10):
raise unittest.SkipTest()
def test_create_datagram_endpoint_reuse_address_error(self):
# bpo-37228: Ensure that explicit passing of `reuse_address=True`
# raises an error, as it is not safe to use SO_REUSEADDR when using UDP
self._skip_create_datagram_endpoint_reuse_addr()
coro = self.loop.create_datagram_endpoint(
lambda: MyDatagramProto(loop=self.loop),
local_addr=('127.0.0.1', 0),
reuse_address=True)
with self.assertRaises(ValueError):
self.loop.run_until_complete(coro)
def test_create_datagram_endpoint_reuse_address_warning(self):
# bpo-37228: Deprecate *reuse_address* parameter
self._skip_create_datagram_endpoint_reuse_addr()
coro = self.loop.create_datagram_endpoint(
lambda: MyDatagramProto(loop=self.loop),
local_addr=('127.0.0.1', 0),
reuse_address=False)
with self.assertWarns(DeprecationWarning):
tr, pr = self.loop.run_until_complete(coro)
tr.close()
self.loop.run_until_complete(pr.done)
class Test_UV_UDP(_TestUDP, tb.UVTestCase):

View File

@ -9,7 +9,7 @@ cdef class UDPTransport(UVBaseTransport):
cdef _connect(self, system.sockaddr* addr, size_t addr_len)
cdef _bind(self, system.sockaddr* addr, bint reuse_addr)
cdef _bind(self, system.sockaddr* addr)
cdef open(self, int family, int sockfd)
cdef _set_broadcast(self, bint on)

View File

@ -104,16 +104,13 @@ cdef class UDPTransport(UVBaseTransport):
exc = convert_error(err)
raise exc
cdef _bind(self, system.sockaddr* addr, bint reuse_addr):
cdef _bind(self, system.sockaddr* addr):
cdef:
int err
int flags = 0
self._ensure_alive()
if reuse_addr:
flags |= uv.UV_UDP_REUSEADDR
err = uv.uv_udp_bind(<uv.uv_udp_t*>self._handle, addr, flags)
if err < 0:
exc = convert_error(err)

View File

@ -199,8 +199,7 @@ cdef extern from "uv.h" nogil:
ctypedef enum uv_udp_flags:
UV_UDP_IPV6ONLY = 1,
UV_UDP_PARTIAL = 2,
UV_UDP_REUSEADDR = 4
UV_UDP_PARTIAL = 2
ctypedef enum uv_membership:
UV_LEAVE_GROUP = 0,

View File

@ -90,6 +90,11 @@ cdef inline socket_dec_io_ref(sock):
sock._decref_socketios()
# Used for deprecation and removal of `loop.create_datagram_endpoint()`'s
# *reuse_address* parameter
_unset = object()
@cython.no_gc_clear
cdef class Loop:
def __cinit__(self):
@ -2924,7 +2929,7 @@ cdef class Loop:
async def create_datagram_endpoint(self, protocol_factory,
local_addr=None, remote_addr=None, *,
family=0, proto=0, flags=0,
reuse_address=None, reuse_port=None,
reuse_address=_unset, reuse_port=None,
allow_broadcast=None, sock=None):
"""A coroutine which creates a datagram endpoint.
@ -2936,11 +2941,6 @@ cdef class Loop:
socket family AF_INET or socket.AF_INET6 depending on host (or
family if specified), socket type SOCK_DGRAM.
reuse_address tells the kernel to reuse a local socket in
TIME_WAIT state, without waiting for its natural timeout to
expire. If not specified it will automatically be set to True on
UNIX.
reuse_port tells the kernel to allow this endpoint to be bound to
the same port as other existing endpoints are bound to, so long as
they all set this flag when being created. This option is not
@ -2965,7 +2965,7 @@ cdef class Loop:
'A UDP Socket was expected, got {!r}'.format(sock))
if (local_addr or remote_addr or
family or proto or flags or
reuse_address or reuse_port or allow_broadcast):
reuse_port or allow_broadcast):
# show the problematic kwargs in exception msg
opts = dict(local_addr=local_addr, remote_addr=remote_addr,
family=family, proto=proto, flags=flags,
@ -2982,7 +2982,16 @@ cdef class Loop:
udp.open(sock.family, sock.fileno())
udp._attach_fileobj(sock)
else:
reuse_address = bool(reuse_address)
if reuse_address is not _unset:
if reuse_address:
raise ValueError("Passing `reuse_address=True` is no "
"longer supported, as the usage of "
"SO_REUSEPORT in UDP poses a significant "
"security concern.")
else:
warnings_warn("The *reuse_address* parameter has been "
"deprecated as of 0.15.", DeprecationWarning,
stacklevel=2)
reuse_port = bool(reuse_port)
if reuse_port and not has_SO_REUSEPORT:
raise ValueError(
@ -3035,7 +3044,7 @@ cdef class Loop:
udp._init(self, lai.ai_family)
if reuse_port:
self._sock_set_reuseport(udp._fileno())
udp._bind(lai.ai_addr, reuse_address)
udp._bind(lai.ai_addr)
except (KeyboardInterrupt, SystemExit):
raise
except BaseException as ex: