New submission from Tim Boddy :
I noticed a memory leak /usr/lib/python3.5/site-packages/OpenSSL/crypto.py in
the definition of the class X509StoreContext. The problem is that the __init__
function calls self._init() then later the function verify_certificate calls
_init() again. In spite of the disclaimer int __init__ about "no adverse
effect", the adverse effect here is that if one does two calls to
X509_STORE_CTX_init on the same X509_STORE_CTX without any intervening calls to
X509_STORE_CTX_cleanup on that same X509_STORE_CTX it will leak one
X509_VERIFY_PARAM and one X509_VERIFY_PARAM_ID.
Here is most of the relevant class:
class X509StoreContext(object):
"""
An X.509 store context.
An X.509 store context is used to carry out the actual verification process
of a certificate in a described context. For describing such a context, see
:class:`X509Store`.
:ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
instance. It is dynamically allocated and automatically garbage
collected.
:ivar _store: See the ``store`` ``__init__`` parameter.
:ivar _cert: See the ``certificate`` ``__init__`` parameter.
:param X509Store store: The certificates which will be trusted for the
purposes of any verifications.
:param X509 certificate: The certificate to be verified.
"""
def __init__(self, store, certificate):
store_ctx = _lib.X509_STORE_CTX_new()
self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
self._store = store
self._cert = certificate
# Make the store context available for use after instantiating this
# class by initializing it now. Per testing, subsequent calls to
# :meth:`_init` have no adverse affect.
self._init()
def _init(self):
"""
Set up the store context for a subsequent verification operation.
"""
Set up the store context for a subsequent verification operation.
"""
ret = _lib.X509_STORE_CTX_init(
self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
)
if ret <= 0:
_raise_current_error()
def _cleanup(self):
"""
Internally cleans up the store context.
The store context can then be reused with a new call to :meth:`_init`.
"""
_lib.X509_STORE_CTX_cleanup(self._store_ctx)
def _exception_from_context(self):
"""
Convert an OpenSSL native context error failure into a Python
exception.
When a call to native OpenSSL X509_verify_cert fails, additional
information about the failure can be obtained from the store context.
"""
errors = [
_lib.X509_STORE_CTX_get_error(self._store_ctx),
_lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
_native(_ffi.string(_lib.X509_verify_cert_error_string(
_lib.X509_STORE_CTX_get_error(self._store_ctx,
]
# A context error should always be associated with a certificate, so we
# expect this call to never return :class:`None`.
_x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
_cert = _lib.X509_dup(_x509)
pycert = X509.__new__(X509)
pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
return X509StoreContextError(errors, pycert)
def set_store(self, store):
"""
Set the context's X.509 store.
.. versionadded:: 0.15
:param X509Store store: The store description which will be used for
the purposes of any *future* verifications.
"""
self._store = store
def verify_certificate(self):
"""
Verify a certificate in a context.
.. versionadded:: 0.15
:raises X509StoreContextError: If an error occurred when validating a
certificate in the context. Sets ``certificate`` attribute to
indicate which certificate caused the error.
"""
# Always re-initialize the store context in case
# :meth:`verify_certificate` is called multiple times.
self._init()
ret = _lib.X509_verify_cert(self._store_ctx)
self._cleanup()
if ret <= 0:
raise self._exception_from_context()
--
messages: 318927
nosy: timboddy
priority: normal
severity: normal
status: open
title: Memory leak in X509StoreContext class.
type: resource usage
versions: Python 3.5
___
Python tracker
<https://bugs.python.org/issue33795>
___
___
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com