|
10 | 10 | #include "Python.h" |
11 | 11 | #include "pycore_call.h" // _PyObject_CallNoArgs() |
12 | 12 | #include "pycore_fileutils.h" // _PyFile_Flush |
| 13 | +#include "pycore_memoryobject.h" // _PyMemoryView_FromBufferProc() |
13 | 14 | #include "pycore_object.h" // _PyObject_GC_UNTRACK() |
14 | 15 | #include "pycore_pyerrors.h" // _Py_FatalErrorFormat() |
15 | 16 | #include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing() |
@@ -254,6 +255,10 @@ typedef struct { |
254 | 255 | isn't ready for writing. */ |
255 | 256 | Py_off_t write_end; |
256 | 257 |
|
| 258 | + /* Region handed to the raw stream by _bufferedreader_raw_read(). */ |
| 259 | + char *raw_read_start; |
| 260 | + Py_ssize_t raw_read_len; |
| 261 | + |
257 | 262 | PyThread_type_lock lock; |
258 | 263 | volatile unsigned long owner; |
259 | 264 |
|
@@ -1619,16 +1624,25 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, |
1619 | 1624 | return 0; |
1620 | 1625 | } |
1621 | 1626 |
|
| 1627 | +/* The memoryview passed to raw.readinto() owns a reference to the buffered |
| 1628 | + object so that storing it in Python code cannot outlive its memory. */ |
| 1629 | +static int |
| 1630 | +_bufferedreader_raw_read_getbuffer(PyObject *op, Py_buffer *view, int flags) |
| 1631 | +{ |
| 1632 | + buffered *self = buffered_CAST(op); |
| 1633 | + return PyBuffer_FillInfo(view, op, self->raw_read_start, |
| 1634 | + self->raw_read_len, 0, flags); |
| 1635 | +} |
| 1636 | + |
1622 | 1637 | static Py_ssize_t |
1623 | 1638 | _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len) |
1624 | 1639 | { |
1625 | | - Py_buffer buf; |
1626 | 1640 | PyObject *memobj, *res; |
1627 | 1641 | Py_ssize_t n; |
1628 | | - /* NOTE: the buffer needn't be released as its object is NULL. */ |
1629 | | - if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1) |
1630 | | - return -1; |
1631 | | - memobj = PyMemoryView_FromBuffer(&buf); |
| 1642 | + self->raw_read_start = start; |
| 1643 | + self->raw_read_len = len; |
| 1644 | + memobj = _PyMemoryView_FromBufferProc((PyObject *)self, PyBUF_CONTIG, |
| 1645 | + _bufferedreader_raw_read_getbuffer); |
1632 | 1646 | if (memobj == NULL) |
1633 | 1647 | return -1; |
1634 | 1648 | /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR |
|
0 commit comments