Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

gh-122179: Fix hashlib.file_digest and non-blocking I/O #122183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 21, 2025
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
9 changes: 8 additions & 1 deletion 9 Doc/library/hashlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ a file or file-like object.
*fileobj* must be a file-like object opened for reading in binary mode.
It accepts file objects from builtin :func:`open`, :class:`~io.BytesIO`
instances, SocketIO objects from :meth:`socket.socket.makefile`, and
similar. The function may bypass Python's I/O and use the file descriptor
similar. *fileobj* must be opened in blocking mode, otherwise a
srittau marked this conversation as resolved.
Show resolved Hide resolved
:exc:`BlockingIOError` may be raised.

The function may bypass Python's I/O and use the file descriptor
from :meth:`~io.IOBase.fileno` directly. *fileobj* must be assumed to be
in an unknown state after this function returns or raises. It is up to
the caller to close *fileobj*.
Expand Down Expand Up @@ -301,6 +304,10 @@ a file or file-like object.

.. versionadded:: 3.11

.. versionchanged:: next
Now raises a :exc:`BlockingIOError` if the file is opened in blocking
mode. Previously, spurious null bytes were added to the digest.


Key derivation
--------------
Expand Down
2 changes: 2 additions & 0 deletions 2 Lib/hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
view = memoryview(buf)
while True:
size = fileobj.readinto(buf)
if size is None:
raise BlockingIOError("I/O operation would block.")
gpshead marked this conversation as resolved.
Show resolved Hide resolved
if size == 0:
break # EOF
digestobj.update(view[:size])
Expand Down
9 changes: 9 additions & 0 deletions 9 Lib/test/test_hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,15 @@ def test_file_digest(self):
with self.assertRaises(ValueError):
hashlib.file_digest(None, "sha256")

class NonBlocking:
def readinto(self, buf):
return None
def readable(self):
return True

with self.assertRaises(BlockingIOError):
gpshead marked this conversation as resolved.
Show resolved Hide resolved
hashlib.file_digest(NonBlocking(), hashlib.sha256)


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:func:`hashlib.file_digest` now raises :exc:`BlockingIOError` when no data
is available during non-blocking I/O. Before, it added spurious null bytes
to the digest.
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.