Skip to content

Commit c772edb

Browse files
committed
Fixed mishandling of large buffers in BaseSocket.sendall()
Fixes #38.
1 parent 629ec0b commit c772edb

File tree

3 files changed

+26
-5
lines changed

3 files changed

+26
-5
lines changed

anyio/_networking.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -143,20 +143,20 @@ async def sendto(self, data: bytes, addr, *, flags: int = 0) -> int:
143143
return self._raw_socket.sendto(data, flags, addr)
144144

145145
async def sendall(self, data: bytes, *, flags: int = 0) -> None:
146-
to_send = len(data)
147-
while to_send > 0:
146+
offset = 0
147+
total = len(data)
148+
buffer = memoryview(data)
149+
while offset < total:
148150
await self._check_cancelled()
149151
try:
150-
sent = self._raw_socket.send(data, flags)
152+
offset += self._raw_socket.send(buffer[offset:], flags)
151153
except (BlockingIOError, ssl.SSLWantWriteError):
152154
await self._wait_writable()
153155
except ssl.SSLWantReadError:
154156
await self._wait_readable()
155157
except ssl.SSLEOFError:
156158
self._raw_socket.close()
157159
raise
158-
else:
159-
to_send -= sent
160160

161161
async def start_tls(self, context: ssl.SSLContext,
162162
server_hostname: Optional[str] = None,

docs/versionhistory.rst

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ Version history
33

44
This library adheres to `Semantic Versioning <http://semver.org/>`_.
55

6+
**UNRELEASED**
7+
8+
- Fixed mishandling of large buffers by ``BaseSocket.sendall()``
9+
610
**1.0.0b1**
711

812
- Initial release

tests/test_networking.py

+17
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,23 @@ async def server():
7272

7373
assert response == b'blahbleh'
7474

75+
@pytest.mark.anyio
76+
async def test_send_large_buffer(self):
77+
async def server():
78+
async with await stream_server.accept() as stream:
79+
await stream.send_all(buffer)
80+
81+
buffer = b'\xff' * 1024 # should exceed the maximum kernel send buffer size
82+
async with create_task_group() as tg:
83+
async with await create_tcp_server(interface='localhost') as stream_server:
84+
await tg.spawn(server)
85+
async with await connect_tcp('localhost', stream_server.port) as client:
86+
response = await client.receive_exactly(len(buffer))
87+
with pytest.raises(IncompleteRead):
88+
await client.receive_exactly(1)
89+
90+
assert response == buffer
91+
7592
@pytest.mark.parametrize('method_name, params', [
7693
('receive_until', [b'\n', 100]),
7794
('receive_exactly', [5])

0 commit comments

Comments
 (0)