Skip to content

Commit 6e78900

Browse files
asvetlovmiss-islington
authored andcommitted
bpo-35589: Prevent buffer copy in sock_sendall() (GH-11418)
No NEWs is needed since the problem was introduced on master only and never released. https://bugs.python.org/issue35589
1 parent bfba8c3 commit 6e78900

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

Lib/asyncio/selector_events.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,32 +428,35 @@ async def sock_sendall(self, sock, data):
428428
if n == len(data):
429429
# all data sent
430430
return
431-
else:
432-
data = bytearray(memoryview(data)[n:])
433431

434432
fut = self.create_future()
435433
fd = sock.fileno()
436434
fut.add_done_callback(
437435
functools.partial(self._sock_write_done, fd))
438-
self.add_writer(fd, self._sock_sendall, fut, sock, data)
436+
# use a trick with a list in closure to store a mutable state
437+
self.add_writer(fd, self._sock_sendall, fut, sock,
438+
memoryview(data), [n])
439439
return await fut
440440

441-
def _sock_sendall(self, fut, sock, data):
441+
def _sock_sendall(self, fut, sock, view, pos):
442442
if fut.done():
443443
# Future cancellation can be scheduled on previous loop iteration
444444
return
445+
start = pos[0]
445446
try:
446-
n = sock.send(data)
447+
n = sock.send(view[start:])
447448
except (BlockingIOError, InterruptedError):
448449
return
449450
except Exception as exc:
450451
fut.set_exception(exc)
451452
return
452453

453-
if n == len(data):
454+
start += n
455+
456+
if start == len(view):
454457
fut.set_result(None)
455458
else:
456-
del data[:n]
459+
pos[0] = start
457460

458461
async def sock_connect(self, sock, address):
459462
"""Connect to a remote socket at address.

0 commit comments

Comments
 (0)