Skip to content

io.BytesIO.getvalue() can return bytes with a stale hash #160181

Closed

Description

@gpshead

Bug report

Bug description:

BytesIO.getvalue() (and read()/peek() covering the whole buffer) returns the internal bytes object without copying. Whether that object may later be modified in place is decided from its reference count alone, so if the caller hashed the result and dropped it, a same-size write(), a write through getbuffer(), or truncate() followed by a refilling write overwrites it in place and keeps the old cached hash.

import io
bio = io.BytesIO()
bio.write(b"abcd")
hash(bio.getvalue())
bio.seek(0)
bio.write(b"efgh")
v = bio.getvalue()
print(v == b"efgh", v in {b"efgh"})  # True False

The same happens when the hashed object was passed to BytesIO(data) and data was dropped. Set and dict lookups with the result silently miss. This dates back to the copy-on-write buffer added in 3.5 (gh-66202). gh-158219 was the same problem in bytearray.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. self-assigned this
    on Oct 22, 2026
  2. added a commit that references this issue on Oct 22, 2026
  3. gvanrossum commented on Oct 22, 2026

    @gvanrossum
    Member

    Isn't someone (Serhiy?) planning to remove the hash?

  4. vstinner commented on Oct 22, 2026

    @vstinner
    Member

    Isn't someone (Serhiy?) planning to remove the hash?

    PyBytesObject.ob_shash is deprecated since Python 3.11. I asked in #158074 if it should be removed or if the deprecation should be removed.

  5. added a commit that references this issue on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

topic-IOtype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions