summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2017-02-10 14:56:55 +0100
committerHynek Schlawack <hs@ox.cx>2017-02-10 14:56:55 +0100
commit868dc3c25404d3be232c209ec15f976e434668d5 (patch)
treec922b90ab3cabce0c2a03f0f7f1dfd1c724196a8
parentb748099426db3963c7b06d2e0aec29e12e016c07 (diff)
downloadpyopenssl-868dc3c25404d3be232c209ec15f976e434668d5.tar.gz
Limit SSL_write bufsize to avoid OverflowErrors (#603)
* limit SSL_write bufsize to avoid OverflowErrors * fix .send() truncation, add test
-rw-r--r--src/OpenSSL/SSL.py10
-rw-r--r--tests/test_ssl.py24
2 files changed, 33 insertions, 1 deletions
diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
index d4158d4..8bbde5b 100644
--- a/src/OpenSSL/SSL.py
+++ b/src/OpenSSL/SSL.py
@@ -1455,6 +1455,8 @@ class Connection(object):
buf = str(buf)
if not isinstance(buf, bytes):
raise TypeError("data must be a memoryview, buffer or byte string")
+ if len(buf) > 2147483647:
+ raise ValueError("Cannot send more than 2**31-1 bytes at once.")
result = _lib.SSL_write(self._ssl, buf, len(buf))
self._raise_ssl_error(self._ssl, result)
@@ -1486,7 +1488,13 @@ class Connection(object):
data = _ffi.new("char[]", buf)
while left_to_send:
- result = _lib.SSL_write(self._ssl, data + total_sent, left_to_send)
+ # SSL_write's num arg is an int,
+ # so we cannot send more than 2**31-1 bytes at once.
+ result = _lib.SSL_write(
+ self._ssl,
+ data + total_sent,
+ min(left_to_send, 2147483647)
+ )
self._raise_ssl_error(self._ssl, result)
total_sent += result
left_to_send -= result
diff --git a/tests/test_ssl.py b/tests/test_ssl.py
index d2a56b7..44a042b 100644
--- a/tests/test_ssl.py
+++ b/tests/test_ssl.py
@@ -6,6 +6,7 @@ Unit tests for :mod:`OpenSSL.SSL`.
"""
import datetime
+import sys
import uuid
from gc import collect, get_referrers
@@ -2662,6 +2663,14 @@ class TestConnectionGetCipherList(object):
assert isinstance(cipher, str)
+class VeryLarge(bytes):
+ """
+ Mock object so that we don't have to allocate 2**31 bytes
+ """
+ def __len__(self):
+ return 2**31
+
+
class TestConnectionSend(object):
"""
Tests for `Connection.send`.
@@ -2725,6 +2734,21 @@ class TestConnectionSend(object):
assert count == 2
assert client.recv(2) == b'xy'
+ @pytest.mark.skipif(
+ sys.maxsize < 2**31,
+ reason="sys.maxsize < 2**31 - test requires 64 bit"
+ )
+ def test_buf_too_large(self):
+ """
+ When passed a buffer containing >= 2**31 bytes,
+ `Connection.send` bails out as SSL_write only
+ accepts an int for the buffer length.
+ """
+ connection = Connection(Context(TLSv1_METHOD), None)
+ with pytest.raises(ValueError) as exc_info:
+ connection.send(VeryLarge())
+ exc_info.match(r"Cannot send more than .+ bytes at once")
+
def _make_memoryview(size):
"""