Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Lib/hmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ def copy(self):
# Call __new__ directly to avoid the expensive __init__.
other = self.__class__.__new__(self.__class__)
other.digest_size = self.digest_size
other.block_size = self.block_size
if self._hmac:
other._hmac = self._hmac.copy()
other._inner = other._outer = None
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_hmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,15 @@ def test_properties(self):
self.assertEqual(h.digest_size, self.digest_size)
self.assertEqual(h.block_size, self.block_size)

def test_copy(self):
# Test a generic copy() and the attributes it exposes.
# See https://github.com/python/cpython/issues/142451.
h1 = self.hmac_new(b"my secret key", digestmod=self.digestname)
h2 = h1.copy()
self.assertEqual(h1.name, h2.name)
self.assertEqual(h1.digest_size, h2.digest_size)
self.assertEqual(h1.block_size, h2.block_size)

def test_repr(self):
# HMAC object representation may differ across implementations
raise NotImplementedError
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:mod:`hmac`: correctly copy :class:`~hmac.HMAC` attributes for objects
copied through :meth:`HMAC.copy() <hmac.HMAC.copy>`. Patch by Bénédikt Tran.
14 changes: 11 additions & 3 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,9 +606,14 @@ get_asn1_utf8name_by_nid(int nid)
{
const char *name = OBJ_nid2ln(nid);
if (name == NULL) {
// In OpenSSL 3.0 and later, OBJ_nid*() are thread-safe and may raise.
assert(ERR_peek_last_error() != 0);
if (ERR_GET_REASON(ERR_peek_last_error()) != OBJ_R_UNKNOWN_NID) {
/* In OpenSSL 3.0 and later, OBJ_nid*() are thread-safe and may raise.
* However, not all versions of OpenSSL set a last error, so we simply
* ignore the last error if none exists.
*
* See https://github.com/python/cpython/issues/142451.
*/
unsigned long errcode = ERR_peek_last_error();
if (errcode && ERR_GET_REASON(errcode) != OBJ_R_UNKNOWN_NID) {
goto error;
}
// fallback to short name and unconditionally propagate errors
Expand Down Expand Up @@ -2255,6 +2260,9 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
return NULL;
}
retval->ctx = ctx;
#ifdef Py_HAS_OPENSSL3_SUPPORT
retval->evp_md_nid = self->evp_md_nid;
#endif
HASHLIB_INIT_MUTEX(retval);
return (PyObject *)retval;
}
Expand Down
Loading