gh-136929: ensure that hashlib.<name> does not raise AttributeError (#136933)
Previously, if OpenSSL was not present and built-in cryptographic extension modules were disabled, requesting `hashlib.<name>` raised `AttributeError` and an ERROR log message with the exception traceback is emitted when importing `hashlib`. Now, the named constructor function will always be available but raises a `ValueError` at runtime indicating that the algorithm is not supported. The log message has also been reworded to be less verbose.
This commit is contained in:
@@ -261,16 +261,39 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
|
||||
return digestobj
|
||||
|
||||
|
||||
__logging = None
|
||||
for __func_name in __always_supported:
|
||||
# try them all, some may not work due to the OpenSSL
|
||||
# version not supporting that algorithm.
|
||||
try:
|
||||
globals()[__func_name] = __get_hash(__func_name)
|
||||
except ValueError:
|
||||
import logging
|
||||
logging.exception('code for hash %s was not found.', __func_name)
|
||||
|
||||
except ValueError as __exc:
|
||||
import logging as __logging
|
||||
__logging.error('hash algorithm %s will not be supported at runtime '
|
||||
'[reason: %s]', __func_name, __exc)
|
||||
# The following code can be simplified in Python 3.19
|
||||
# once "string" is removed from the signature.
|
||||
__code = f'''\
|
||||
def {__func_name}(data=__UNSET, *, usedforsecurity=True, string=__UNSET):
|
||||
if data is __UNSET and string is not __UNSET:
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"the 'string' keyword parameter is deprecated since "
|
||||
"Python 3.15 and slated for removal in Python 3.19; "
|
||||
"use the 'data' keyword parameter or pass the data "
|
||||
"to hash as a positional argument instead",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
if data is not __UNSET and string is not __UNSET:
|
||||
raise TypeError("'data' and 'string' are mutually exclusive "
|
||||
"and support for 'string' keyword parameter "
|
||||
"is slated for removal in a future version.")
|
||||
raise ValueError("unsupported hash algorithm {__func_name}")
|
||||
'''
|
||||
exec(__code, {"__UNSET": object()}, __locals := {})
|
||||
globals()[__func_name] = __locals[__func_name]
|
||||
del __exc, __code, __locals
|
||||
|
||||
# Cleanup locals()
|
||||
del __always_supported, __func_name, __get_hash
|
||||
del __py_new, __hash_new, __get_openssl_constructor
|
||||
del __logging
|
||||
|
||||
Reference in New Issue
Block a user