`_pyio.BufferedReader.readinto()` can raise `ValueError` after partially filling the destination
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 77.2k
- Forks
- 35.9k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
Bug report
Bug description:
The pure Python implementation of BufferedReader.readinto() can raise ValueError for a valid writable buffer after partially modifying it.
import io
import _pyio
for module in (io, _pyio):
reader = module.BufferedReader(module.BytesIO(b"abcd"), buffer_size=2)
assert reader.read(1) == b"a"
destination = bytearray(2)
try:
result = reader.readinto(destination)
except ValueError as error:
result = f"{type(error).__name__}: {error}"
print(module.__name__, result, destination, reader.read())
Current output on main:
io 2 bytearray(b'bc') b'd'
_pyio ValueError: memoryview assignment: lvalue and rvalue have different structures bytearray(b'b\x00') b'cd'
_pyio should match io: return 2, fill the destination with b"bc", and leave b"d" unread. readinto() first partially fills the destination with data from its internal buffer, then refills that buffer with more data than fits in the remaining space. It then raises ValueError. Because the destination has already been modified and the stream has advanced when the exception is raised, the caller receives no byte count and cannot safely retry on a non-seekable stream.
_pyio.BufferedRandom.readinto() and _pyio.BufferedRWPair.readinto() are also affected because they use the same reader path.
I am working on a PR with a regression test shared by the C and pure Python implementations.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
- gh-155075
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne am Einstiegspunkt _pyio.BufferedReader.readinto() und führe den Reproducer aus dem Issue aus, wobei du ihn mit io.BufferedReader.readinto() vergleichst. Als erledigt gilt, wenn der reine Python-Pfad 2 zurückgibt, das Ziel mit b"bc" füllt, b"d" ungelesen lässt und das für BufferedRandom und BufferedRWPair beschriebene gemeinsame Regressionsverhalten abdeckt.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- backend
- Issue-Typ
- Bug
- Schwierigkeit
- 3/5
- Geschätzter Aufwand
- 1-2 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 25/100