Skip to content

Commit

Permalink
Improve UDPTransport.sendto address validation (fixes: #214)
Browse files Browse the repository at this point in the history
When UDPTransport.sendto is called with a destination address, only
perform the validation once and store the result in an LRU cache. Also
store some of the socket's properties (family, proto, type) as integers
to avoid repeatedly fetching these properties and converting them to integers.
  • Loading branch information
jlaine committed Jan 8, 2019
1 parent df0e543 commit 0016813
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 13 deletions.
3 changes: 3 additions & 0 deletions uvloop/handles/udp.pxd
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
cdef class UDPTransport(UVBaseTransport):
cdef:
object sock
int sock_family
int sock_proto
int sock_type
UVPoll poll
object address
object buffer
Expand Down
34 changes: 21 additions & 13 deletions uvloop/handles/udp.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import socket
import functools


cdef class UDPTransport(UVBaseTransport):

Expand All @@ -17,6 +18,9 @@ cdef class UDPTransport(UVBaseTransport):
socket_inc_io_ref(sock)

self.sock = sock
self.sock_family = sock.family
self.sock_proto = sock.proto
self.sock_type = sock.type
self.address = r_addr
self.poll = UVPoll.new(loop, sock.fileno())
self._finish_init()
Expand Down Expand Up @@ -143,18 +147,8 @@ cdef class UDPTransport(UVBaseTransport):
raise ValueError(
'Invalid address: must be None or {}'.format(self.address))

if addr is not None and self.sock.family != socket.AF_UNIX:
addrinfo = __static_getaddrinfo_pyaddr(
addr[0], addr[1],
uv.AF_UNSPEC, self.sock.type, self.sock.proto, 0)
if addrinfo is None:
raise ValueError(
'UDP.sendto(): address {!r} requires a DNS lookup'.format(
addr))
if addrinfo[0] != self.sock.family:
raise ValueError(
'UDP.sendto(): {!r} socket family mismatch'.format(
addr))
if addr is not None and self.sock_family != uv.AF_UNIX:
self._validate_address(addr)

if self._conn_lost and self._address:
if self._conn_lost >= LOG_THRESHOLD_FOR_CONNLOST_WRITES:
Expand Down Expand Up @@ -188,3 +182,17 @@ cdef class UDPTransport(UVBaseTransport):
# Ensure that what we buffer is immutable.
self.buffer.append((bytes(data), addr))
self._maybe_pause_protocol()

@functools.lru_cache()
def _validate_address(self, object addr):
addrinfo = __static_getaddrinfo_pyaddr(
addr[0], addr[1],
uv.AF_UNSPEC, self.sock_type, self.sock_proto, 0)
if addrinfo is None:
raise ValueError(
'UDP.sendto(): address {!r} requires a DNS lookup'.format(
addr))
if addrinfo[0] != self.sock_family:
raise ValueError(
'UDP.sendto(): {!r} socket family mismatch'.format(
addr))

0 comments on commit 0016813

Please sign in to comment.