]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-142451: correctly copy HMAC attributes in `HMAC.copy()` (#142510)
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>
Sun, 14 Dec 2025 08:45:36 +0000 (09:45 +0100)
committerGitHub <noreply@github.com>
Sun, 14 Dec 2025 08:45:36 +0000 (09:45 +0100)
Lib/hmac.py
Lib/test/test_hmac.py
Misc/NEWS.d/next/Library/2025-12-10-11-02-53.gh-issue-142451.eCLvhG.rst [new file with mode: 0644]
Modules/_hashopenssl.c

index 9d3fae8b1b15970be386d9ff610b3272c2bb2a09..e0c040bcd5fe3d2e2d50e3937c9a53d739fa870f 100644 (file)
@@ -171,6 +171,7 @@ class HMAC:
         # 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
index 7634deeb1d8eb9be1207189259af9c8653e272ef..17888a9f286c8f5c89a70b53cfafa8a9ec87f2e3 100644 (file)
@@ -1076,6 +1076,15 @@ class SanityTestCaseMixin(CreatorMixin):
         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
diff --git a/Misc/NEWS.d/next/Library/2025-12-10-11-02-53.gh-issue-142451.eCLvhG.rst b/Misc/NEWS.d/next/Library/2025-12-10-11-02-53.gh-issue-142451.eCLvhG.rst
new file mode 100644 (file)
index 0000000..3726d41
--- /dev/null
@@ -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.
index 19089b009f7911fd2ea56f78d394753790233c5b..77832a768e0cbcb4aa4cef4cfead85348c09b403 100644 (file)
@@ -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
@@ -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;
 }