Skip to content

Commit

Permalink
bpo-35941: Fix performance regression in new code (GH-12610)
Browse files Browse the repository at this point in the history
Accumulate certificates in a set instead of doing a costly list contain
operation. A Windows cert store can easily contain over hundred
certificates. The old code would result in way over 5,000 comparison
operations

Signed-off-by: Christian Heimes <christian@python.org>
  • Loading branch information
tiran authored and zooba committed Sep 9, 2019
1 parent 09090d0 commit 915cd3f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 30 deletions.
4 changes: 2 additions & 2 deletions Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,8 +835,8 @@ def test_enum_certificates(self):
cert, enc, trust = element
self.assertIsInstance(cert, bytes)
self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
self.assertIsInstance(trust, (set, bool))
if isinstance(trust, set):
self.assertIsInstance(trust, (frozenset, set, bool))
if isinstance(trust, (frozenset, set)):
trust_oids.update(trust)

serverAuth = "1.3.6.1.5.5.7.3.1"
Expand Down
55 changes: 27 additions & 28 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5517,7 +5517,7 @@ parseKeyUsage(PCCERT_CONTEXT pCertCtx, DWORD flags)
}
return PyErr_SetFromWindowsErr(error);
}
retval = PySet_New(NULL);
retval = PyFrozenSet_New(NULL);
if (retval == NULL) {
goto error;
}
Expand Down Expand Up @@ -5592,19 +5592,6 @@ ssl_collect_certificates(const char *store_name)
return hCollectionStore;
}

/* code from Objects/listobject.c */

static int
list_contains(PyListObject *a, PyObject *el)
{
Py_ssize_t i;
int cmp;

for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
cmp = PyObject_RichCompareBool(PyList_GET_ITEM(a, i), el, Py_EQ);
return cmp;
}

/*[clinic input]
_ssl.enum_certificates
store_name: str
Expand All @@ -5627,7 +5614,7 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name)
PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL;
PyObject *result = NULL;

result = PyList_New(0);
result = PySet_New(NULL);
if (result == NULL) {
return NULL;
}
Expand Down Expand Up @@ -5667,11 +5654,10 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name)
enc = NULL;
PyTuple_SET_ITEM(tup, 2, keyusage);
keyusage = NULL;
if (!list_contains((PyListObject*)result, tup)) {
if (PyList_Append(result, tup) < 0) {
Py_CLEAR(result);
break;
}
if (PySet_Add(result, tup) == -1) {
Py_CLEAR(result);
Py_CLEAR(tup);
break;
}
Py_CLEAR(tup);
}
Expand All @@ -5695,7 +5681,14 @@ _ssl_enum_certificates_impl(PyObject *module, const char *store_name)
return PyErr_SetFromWindowsErr(GetLastError());
}

return result;
/* convert set to list */
if (result == NULL) {
return NULL;
} else {
PyObject *lst = PySequence_List(result);
Py_DECREF(result);
return lst;
}
}

/*[clinic input]
Expand All @@ -5719,7 +5712,7 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name)
PyObject *crl = NULL, *enc = NULL, *tup = NULL;
PyObject *result = NULL;

result = PyList_New(0);
result = PySet_New(NULL);
if (result == NULL) {
return NULL;
}
Expand Down Expand Up @@ -5749,11 +5742,10 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name)
PyTuple_SET_ITEM(tup, 1, enc);
enc = NULL;

if (!list_contains((PyListObject*)result, tup)) {
if (PyList_Append(result, tup) < 0) {
Py_CLEAR(result);
break;
}
if (PySet_Add(result, tup) == -1) {
Py_CLEAR(result);
Py_CLEAR(tup);
break;
}
Py_CLEAR(tup);
}
Expand All @@ -5775,7 +5767,14 @@ _ssl_enum_crls_impl(PyObject *module, const char *store_name)
Py_XDECREF(result);
return PyErr_SetFromWindowsErr(GetLastError());
}
return result;
/* convert set to list */
if (result == NULL) {
return NULL;
} else {
PyObject *lst = PySequence_List(result);
Py_DECREF(result);
return lst;
}
}

#endif /* _MSC_VER */
Expand Down

0 comments on commit 915cd3f

Please sign in to comment.