Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions 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.")
if size == 0:
break # EOF
digestobj.update(view[:size])
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,15 @@ def test_file_digest(self):
with open(os_helper.TESTFN, "wb") as f:
hashlib.file_digest(f, "sha256")

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

with self.assertRaises(BlockingIOError):
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.