summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCory Benfield <lukasaoz@gmail.com>2016-11-28 12:17:08 +0000
committerHynek Schlawack <hs@ox.cx>2016-11-28 13:17:08 +0100
commite62840e19c5f1640afff1ff4d84df05cda652085 (patch)
treea5e903d910e8412c1571b17766cc96a0152217ae
parentf189de9becf14840712b01877ebb1f08c26f894c (diff)
downloadpyopenssl-e62840e19c5f1640afff1ff4d84df05cda652085.tar.gz
Don't zero memory when we don't have to. (#578)
-rw-r--r--CHANGELOG.rst4
-rw-r--r--src/OpenSSL/SSL.py15
-rw-r--r--src/OpenSSL/_util.py6
3 files changed, 18 insertions, 7 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 19cebf1..56c3c74 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -25,6 +25,10 @@ Changes:
- Added ``OpenSSL.X509Store.set_time()`` to set a custom verification time when verifying certificate chains.
`#567 <https://github.com/pyca/pyopenssl/pull/567>`_
+- Changed the ``SSL`` module's memory allocation policy to avoid zeroing memory it allocates when unnecessary.
+ This reduces CPU usage and memory allocation time by an amount proportional to the size of the allocation.
+ For applications that process a lot of TLS data or that use very lage allocations this can provide considerable performance improvements.
+ `#578 <https://github.com/pyca/pyopenssl/pull/578>`_
----
diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
index f92c064..63a0b7e 100644
--- a/src/OpenSSL/SSL.py
+++ b/src/OpenSSL/SSL.py
@@ -18,6 +18,7 @@ from OpenSSL._util import (
native as _native,
path_string as _path_string,
text_to_bytes_and_warn as _text_to_bytes_and_warn,
+ no_zero_allocator as _no_zero_allocator,
)
from OpenSSL.crypto import (
@@ -1297,7 +1298,7 @@ class Connection(object):
all other flags are ignored.
:return: The string read from the Connection
"""
- buf = _ffi.new("char[]", bufsiz)
+ buf = _no_zero_allocator("char[]", bufsiz)
if flags is not None and flags & socket.MSG_PEEK:
result = _lib.SSL_peek(self._ssl, buf, bufsiz)
else:
@@ -1328,7 +1329,7 @@ class Connection(object):
# We need to create a temporary buffer. This is annoying, it would be
# better if we could pass memoryviews straight into the SSL_read call,
# but right now we can't. Revisit this if CFFI gets that ability.
- buf = _ffi.new("char[]", nbytes)
+ buf = _no_zero_allocator("char[]", nbytes)
if flags is not None and flags & socket.MSG_PEEK:
result = _lib.SSL_peek(self._ssl, buf, nbytes)
else:
@@ -1379,7 +1380,7 @@ class Connection(object):
if not isinstance(bufsiz, integer_types):
raise TypeError("bufsiz must be an integer")
- buf = _ffi.new("char[]", bufsiz)
+ buf = _no_zero_allocator("char[]", bufsiz)
result = _lib.BIO_read(self._from_ssl, buf, bufsiz)
if result <= 0:
self._handle_bio_errors(self._from_ssl, result)
@@ -1616,7 +1617,7 @@ class Connection(object):
return None
length = _lib.SSL_get_server_random(self._ssl, _ffi.NULL, 0)
assert length > 0
- outp = _ffi.new("unsigned char[]", length)
+ outp = _no_zero_allocator("unsigned char[]", length)
_lib.SSL_get_server_random(self._ssl, outp, length)
return _ffi.buffer(outp, length)[:]
@@ -1632,7 +1633,7 @@ class Connection(object):
length = _lib.SSL_get_client_random(self._ssl, _ffi.NULL, 0)
assert length > 0
- outp = _ffi.new("unsigned char[]", length)
+ outp = _no_zero_allocator("unsigned char[]", length)
_lib.SSL_get_client_random(self._ssl, outp, length)
return _ffi.buffer(outp, length)[:]
@@ -1648,7 +1649,7 @@ class Connection(object):
length = _lib.SSL_SESSION_get_master_key(session, _ffi.NULL, 0)
assert length > 0
- outp = _ffi.new("unsigned char[]", length)
+ outp = _no_zero_allocator("unsigned char[]", length)
_lib.SSL_SESSION_get_master_key(session, outp, length)
return _ffi.buffer(outp, length)[:]
@@ -1788,7 +1789,7 @@ class Connection(object):
# No Finished message so far.
return None
- buf = _ffi.new("char[]", size)
+ buf = _no_zero_allocator("char[]", size)
function(self._ssl, buf, size)
return _ffi.buffer(buf, size)[:]
diff --git a/src/OpenSSL/_util.py b/src/OpenSSL/_util.py
index 48bcbf5..cf8b888 100644
--- a/src/OpenSSL/_util.py
+++ b/src/OpenSSL/_util.py
@@ -12,6 +12,12 @@ ffi = binding.ffi
lib = binding.lib
+# This is a special CFFI allocator that does not bother to zero its memory
+# after allocation. This has vastly better performance on large allocations and
+# so should be used whenever we don't need the memory zeroed out.
+no_zero_allocator = ffi.new_allocator(should_clear_after_alloc=False)
+
+
def text(charp):
"""
Get a native string type representing of the given CFFI ``char*`` object.