Skip to content

Commit 8ae1a23

Browse files
authored
gh-110357: hashlib no longer logs at import when a guaranteed hash is unavailable (GH-152538)
When a normally-guaranteed hash algorithm cannot be constructed at import time (e.g. an OpenSSL FIPS configuration excludes it from the default provider, or the build used --without-builtin-hashlib-hashes), importing hashlib emitted an "ERROR:root:hash algorithm ... will not be supported at runtime" message to stderr. For the many programs that never use the missing algorithm this is pure noise. Worse, logging.error() lazily calls logging.basicConfig(), which mutates the root logger's handlers -- a global side effect that the test suite flags as an altered execution environment. Stop logging in that path. Code that actually uses a missing algorithm still gets a clear ValueError from the stub constructor installed in its place. The stray output has shown up incidentally in FIPS / "No Builtin Hashes" buildbot reports for years (e.g. gh-110357, gh-76902) without being the reported subject.
1 parent 2670cb0 commit 8ae1a23

3 files changed

Lines changed: 20 additions & 13 deletions

File tree

Doc/library/hashlib.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,15 @@ hash supplied more than 2047 bytes of data at once in its constructor or
5050
.. index:: single: OpenSSL; (use in module hashlib)
5151

5252
Constructors for hash algorithms that are always present in this module are
53-
:func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`, :func:`sha512`,
54-
:func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`, :func:`sha3_512`,
55-
:func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and :func:`blake2s`.
56-
:func:`md5` is normally available as well, though it may be missing or blocked
57-
if you are using a rare "FIPS compliant" build of Python.
58-
These correspond to :data:`algorithms_guaranteed`.
53+
:func:`md5`, :func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`,
54+
:func:`sha512`, :func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`,
55+
:func:`sha3_512`, :func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and
56+
:func:`blake2s`. These correspond to :data:`algorithms_guaranteed`.
57+
58+
Any of these may nonetheless be missing or blocked in unusual environments,
59+
such as a rare "FIPS compliant" build of Python or when OpenSSL's "FIPS mode"
60+
is configured to exclude some algorithms from its default provider. Calling
61+
the constructor of an algorithm that is unavailable raises :exc:`ValueError`.
5962

6063
Additional algorithms may also be available if your Python distribution's
6164
:mod:`!hashlib` was linked against a build of OpenSSL that provides others.

Lib/hashlib.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -261,16 +261,15 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
261261
return digestobj
262262

263263

264-
__logging = None
265264
for __func_name in __always_supported:
266265
# try them all, some may not work due to the OpenSSL
267266
# version not supporting that algorithm.
268267
try:
269268
globals()[__func_name] = __get_hash(__func_name)
270-
except ValueError as __exc:
271-
import logging as __logging
272-
__logging.error('hash algorithm %s will not be supported at runtime '
273-
'[reason: %s]', __func_name, __exc)
269+
except ValueError:
270+
# Don't log here: logging at import time has global side effects and
271+
# would tell the wrong audience; code that uses a missing algorithm
272+
# gets a ValueError from the stub installed below.
274273
# The following code can be simplified in Python 3.19
275274
# once "string" is removed from the signature.
276275
__code = f'''\
@@ -291,9 +290,8 @@ def {__func_name}(data=__UNSET, *, usedforsecurity=True, string=__UNSET):
291290
'''
292291
exec(__code, {"__UNSET": object()}, __locals := {})
293292
globals()[__func_name] = __locals[__func_name]
294-
del __exc, __code, __locals
293+
del __code, __locals
295294

296295
# Cleanup locals()
297296
del __always_supported, __func_name, __get_hash
298297
del __py_new, __hash_new, __get_openssl_constructor
299-
del __logging
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Importing :mod:`hashlib` no longer logs an error to stderr when a normally
2+
guaranteed hash algorithm is unavailable in the current runtime (for example
3+
under an OpenSSL FIPS configuration or a build using
4+
:option:`--without-builtin-hashlib-hashes <--with-builtin-hashlib-hashes>`).
5+
Code that actually uses the missing algorithm still gets a clear
6+
:exc:`ValueError`.

0 commit comments

Comments
 (0)