Skip to content

Commit d791cd9

Browse files
committed
gh-145301: Fix double-free in hmac module initialization
1 parent dc3e19c commit d791cd9

File tree

4 files changed

+25
-41
lines changed

4 files changed

+25
-41
lines changed

Lib/test/test_hashlib.py

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@
1616
import sys
1717
import sysconfig
1818
import tempfile
19+
import textwrap
1920
import threading
2021
import unittest
21-
import subprocess
22-
import textwrap
2322
from test import support
2423
from test.support import _4G, bigmemtest
2524
from test.support import hashlib_helper
26-
from test.support.import_helper import import_fresh_module
25+
from test.support import import_helper
2726
from test.support import requires_resource
2827
from test.support import threading_helper
28+
from test.support.script_helper import assert_python_ok
2929
from http.client import HTTPException
3030

3131

@@ -39,7 +39,7 @@
3939
builtin_hashes = set(map(str.strip, builtin_hash_names))
4040

4141
# Public 'hashlib' module with OpenSSL backend for PBKDF2.
42-
openssl_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
42+
openssl_hashlib = import_helper.import_fresh_module('hashlib', fresh=['_hashlib'])
4343

4444
try:
4545
import _hashlib
@@ -68,6 +68,7 @@ def get_fips_mode():
6868

6969
requires_sha3 = unittest.skipUnless(_sha3, 'requires _sha3')
7070

71+
_testcapi = import_helper.import_module('_testcapi')
7172

7273
def hexstr(s):
7374
assert isinstance(s, bytes), repr(s)
@@ -1204,23 +1205,13 @@ def test_readonly_types(self):
12041205
hash_type.value = False
12051206

12061207
@unittest.skipUnless(HASH is not None, 'need _hashlib')
1208+
@unittest.skipUnless(hasattr(_testcapi, 'set_nomemory'),
1209+
'need _testcapi.set_nomemory()')
12071210
def test_hashlib_init_memory_error_no_df(self):
12081211
"""gh-145301 regression test."""
1209-
1210-
try:
1211-
import _testcapi
1212-
if not hasattr(_testcapi, 'set_nomemory'):
1213-
self.skipTest('requires _testcapi.set_nomemory')
1214-
except ImportError:
1215-
self.skipTest('requires _testcapi')
1216-
12171212
code = textwrap.dedent("""
12181213
import sys
12191214
import _testcapi
1220-
1221-
if '_hashlib' in sys.modules:
1222-
del sys.modules['_hashlib']
1223-
12241215
_testcapi.set_nomemory(40, 41)
12251216
try:
12261217
import _hashlib
@@ -1229,16 +1220,7 @@ def test_hashlib_init_memory_error_no_df(self):
12291220
finally:
12301221
_testcapi.remove_mem_hooks()
12311222
""")
1232-
1233-
rc = subprocess.call(
1234-
[sys.executable, '-c', code],
1235-
stdout=subprocess.DEVNULL,
1236-
stderr=subprocess.DEVNULL,
1237-
)
1238-
# rc < 0 means crash (signal on Unix), which indicates double-free
1239-
# rc >= 0 means normal exit (even with MemoryError), which is expected
1240-
self.assertGreaterEqual(rc, 0,
1241-
"Process crashed - Loss double-free in _hashlib")
1223+
assert_python_ok('-c', code)
12421224

12431225

12441226
class KDFTests(unittest.TestCase):
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
Fix a crash when :mod:`hashlib` or :mod:`hmac` C extension module initialization fails.
1+
:mod:`hashlib`: fix a crash when the initialization of the underlying C
2+
extension module fails.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:mod:`hmac`: fix a crash when the initialization of the underlying C
2+
extension module fails.

Modules/hmacmodule.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,20 +1453,19 @@ py_hmac_hinfo_ht_new(void)
14531453
assert(value->display_name == NULL);
14541454
value->refcnt = 0;
14551455

1456-
#define Py_HMAC_HINFO_LINK(KEY) \
1457-
do { \
1458-
int rc = py_hmac_hinfo_ht_add(table, KEY, value); \
1459-
if (rc < 0) { \
1460-
/* entry may already be in ht, will be freed by \
1461-
_Py_hashtable_destroy() */ \
1462-
if (value->refcnt == 0) { \
1463-
PyMem_Free(value); \
1464-
} \
1465-
goto error; \
1466-
} \
1467-
else if (rc == 1) { \
1468-
value->refcnt++; \
1469-
} \
1456+
#define Py_HMAC_HINFO_LINK(KEY) \
1457+
do { \
1458+
int rc = py_hmac_hinfo_ht_add(table, KEY, value); \
1459+
if (rc < 0) { \
1460+
/* entry may already be in ht, freed upon exit */ \
1461+
if (value->refcnt == 0) { \
1462+
PyMem_Free(value); \
1463+
} \
1464+
goto error; \
1465+
} \
1466+
else if (rc == 1) { \
1467+
value->refcnt++; \
1468+
} \
14701469
} while (0)
14711470
Py_HMAC_HINFO_LINK(e->name);
14721471
Py_HMAC_HINFO_LINK(e->hashlib_name);

0 commit comments

Comments
 (0)