1 /*
2     An implementation of Buffered I/O as defined by PEP 3116 - "New I/O"
3 
4     Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter,
5     BufferedRandom.
6 
7     Written by Amaury Forgeot d'Arc and Antoine Pitrou
8 */
9 
10 #define PY_SSIZE_T_CLEAN
11 #include "Python.h"
12 #include "pycore_object.h"
13 #include "pycore_pystate.h"
14 #include "structmember.h"
15 #include "pythread.h"
16 #include "_iomodule.h"
17 
18 /*[clinic input]
19 module _io
20 class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type"
21 class _io._Buffered "buffered *" "&PyBufferedIOBase_Type"
22 class _io.BufferedReader "buffered *" "&PyBufferedReader_Type"
23 class _io.BufferedWriter "buffered *" "&PyBufferedWriter_Type"
24 class _io.BufferedRWPair "rwpair *" "&PyBufferedRWPair_Type"
25 class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type"
26 [clinic start generated code]*/
27 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/
28 
29 _Py_IDENTIFIER(close);
30 _Py_IDENTIFIER(_dealloc_warn);
31 _Py_IDENTIFIER(flush);
32 _Py_IDENTIFIER(isatty);
33 _Py_IDENTIFIER(mode);
34 _Py_IDENTIFIER(name);
35 _Py_IDENTIFIER(peek);
36 _Py_IDENTIFIER(read);
37 _Py_IDENTIFIER(read1);
38 _Py_IDENTIFIER(readable);
39 _Py_IDENTIFIER(readinto);
40 _Py_IDENTIFIER(readinto1);
41 _Py_IDENTIFIER(writable);
42 _Py_IDENTIFIER(write);
43 
44 /*
45  * BufferedIOBase class, inherits from IOBase.
46  */
47 PyDoc_STRVAR(bufferediobase_doc,
48     "Base class for buffered IO objects.\n"
49     "\n"
50     "The main difference with RawIOBase is that the read() method\n"
51     "supports omitting the size argument, and does not have a default\n"
52     "implementation that defers to readinto().\n"
53     "\n"
54     "In addition, read(), readinto() and write() may raise\n"
55     "BlockingIOError if the underlying raw stream is in non-blocking\n"
56     "mode and not ready; unlike their raw counterparts, they will never\n"
57     "return None.\n"
58     "\n"
59     "A typical implementation should not inherit from a RawIOBase\n"
60     "implementation, but wrap one.\n"
61     );
62 
63 static PyObject *
_bufferediobase_readinto_generic(PyObject * self,Py_buffer * buffer,char readinto1)64 _bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1)
65 {
66     Py_ssize_t len;
67     PyObject *data;
68 
69     data = _PyObject_CallMethodId(self,
70                                   readinto1 ? &PyId_read1 : &PyId_read,
71                                   "n", buffer->len);
72     if (data == NULL)
73         return NULL;
74 
75     if (!PyBytes_Check(data)) {
76         Py_DECREF(data);
77         PyErr_SetString(PyExc_TypeError, "read() should return bytes");
78         return NULL;
79     }
80 
81     len = PyBytes_GET_SIZE(data);
82     if (len > buffer->len) {
83         PyErr_Format(PyExc_ValueError,
84                      "read() returned too much data: "
85                      "%zd bytes requested, %zd returned",
86                      buffer->len, len);
87         Py_DECREF(data);
88         return NULL;
89     }
90     memcpy(buffer->buf, PyBytes_AS_STRING(data), len);
91 
92     Py_DECREF(data);
93 
94     return PyLong_FromSsize_t(len);
95 }
96 
97 /*[clinic input]
98 _io._BufferedIOBase.readinto
99     buffer: Py_buffer(accept={rwbuffer})
100     /
101 [clinic start generated code]*/
102 
103 static PyObject *
_io__BufferedIOBase_readinto_impl(PyObject * self,Py_buffer * buffer)104 _io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer)
105 /*[clinic end generated code: output=8c8cda6684af8038 input=00a6b9a38f29830a]*/
106 {
107     return _bufferediobase_readinto_generic(self, buffer, 0);
108 }
109 
110 /*[clinic input]
111 _io._BufferedIOBase.readinto1
112     buffer: Py_buffer(accept={rwbuffer})
113     /
114 [clinic start generated code]*/
115 
116 static PyObject *
_io__BufferedIOBase_readinto1_impl(PyObject * self,Py_buffer * buffer)117 _io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer)
118 /*[clinic end generated code: output=358623e4fd2b69d3 input=ebad75b4aadfb9be]*/
119 {
120     return _bufferediobase_readinto_generic(self, buffer, 1);
121 }
122 
123 static PyObject *
bufferediobase_unsupported(const char * message)124 bufferediobase_unsupported(const char *message)
125 {
126     _PyIO_State *state = IO_STATE();
127     if (state != NULL)
128         PyErr_SetString(state->unsupported_operation, message);
129     return NULL;
130 }
131 
132 /*[clinic input]
133 _io._BufferedIOBase.detach
134 
135 Disconnect this buffer from its underlying raw stream and return it.
136 
137 After the raw stream has been detached, the buffer is in an unusable
138 state.
139 [clinic start generated code]*/
140 
141 static PyObject *
_io__BufferedIOBase_detach_impl(PyObject * self)142 _io__BufferedIOBase_detach_impl(PyObject *self)
143 /*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/
144 {
145     return bufferediobase_unsupported("detach");
146 }
147 
148 PyDoc_STRVAR(bufferediobase_read_doc,
149     "Read and return up to n bytes.\n"
150     "\n"
151     "If the argument is omitted, None, or negative, reads and\n"
152     "returns all data until EOF.\n"
153     "\n"
154     "If the argument is positive, and the underlying raw stream is\n"
155     "not 'interactive', multiple raw reads may be issued to satisfy\n"
156     "the byte count (unless EOF is reached first).  But for\n"
157     "interactive raw streams (as well as sockets and pipes), at most\n"
158     "one raw read will be issued, and a short result does not imply\n"
159     "that EOF is imminent.\n"
160     "\n"
161     "Returns an empty bytes object on EOF.\n"
162     "\n"
163     "Returns None if the underlying raw stream was open in non-blocking\n"
164     "mode and no data is available at the moment.\n");
165 
166 static PyObject *
bufferediobase_read(PyObject * self,PyObject * args)167 bufferediobase_read(PyObject *self, PyObject *args)
168 {
169     return bufferediobase_unsupported("read");
170 }
171 
172 PyDoc_STRVAR(bufferediobase_read1_doc,
173     "Read and return up to n bytes, with at most one read() call\n"
174     "to the underlying raw stream. A short result does not imply\n"
175     "that EOF is imminent.\n"
176     "\n"
177     "Returns an empty bytes object on EOF.\n");
178 
179 static PyObject *
bufferediobase_read1(PyObject * self,PyObject * args)180 bufferediobase_read1(PyObject *self, PyObject *args)
181 {
182     return bufferediobase_unsupported("read1");
183 }
184 
185 PyDoc_STRVAR(bufferediobase_write_doc,
186     "Write the given buffer to the IO stream.\n"
187     "\n"
188     "Returns the number of bytes written, which is always the length of b\n"
189     "in bytes.\n"
190     "\n"
191     "Raises BlockingIOError if the buffer is full and the\n"
192     "underlying raw stream cannot accept more data at the moment.\n");
193 
194 static PyObject *
bufferediobase_write(PyObject * self,PyObject * args)195 bufferediobase_write(PyObject *self, PyObject *args)
196 {
197     return bufferediobase_unsupported("write");
198 }
199 
200 
201 typedef struct {
202     PyObject_HEAD
203 
204     PyObject *raw;
205     int ok;    /* Initialized? */
206     int detached;
207     int readable;
208     int writable;
209     char finalizing;
210 
211     /* True if this is a vanilla Buffered object (rather than a user derived
212        class) *and* the raw stream is a vanilla FileIO object. */
213     int fast_closed_checks;
214 
215     /* Absolute position inside the raw stream (-1 if unknown). */
216     Py_off_t abs_pos;
217 
218     /* A static buffer of size `buffer_size` */
219     char *buffer;
220     /* Current logical position in the buffer. */
221     Py_off_t pos;
222     /* Position of the raw stream in the buffer. */
223     Py_off_t raw_pos;
224 
225     /* Just after the last buffered byte in the buffer, or -1 if the buffer
226        isn't ready for reading. */
227     Py_off_t read_end;
228 
229     /* Just after the last byte actually written */
230     Py_off_t write_pos;
231     /* Just after the last byte waiting to be written, or -1 if the buffer
232        isn't ready for writing. */
233     Py_off_t write_end;
234 
235     PyThread_type_lock lock;
236     volatile unsigned long owner;
237 
238     Py_ssize_t buffer_size;
239     Py_ssize_t buffer_mask;
240 
241     PyObject *dict;
242     PyObject *weakreflist;
243 } buffered;
244 
245 /*
246     Implementation notes:
247 
248     * BufferedReader, BufferedWriter and BufferedRandom try to share most
249       methods (this is helped by the members `readable` and `writable`, which
250       are initialized in the respective constructors)
251     * They also share a single buffer for reading and writing. This enables
252       interleaved reads and writes without flushing. It also makes the logic
253       a bit trickier to get right.
254     * The absolute position of the raw stream is cached, if possible, in the
255       `abs_pos` member. It must be updated every time an operation is done
256       on the raw stream. If not sure, it can be reinitialized by calling
257       _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek()
258       also does it). To read it, use RAW_TELL().
259     * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and
260       _bufferedwriter_flush_unlocked do a lot of useful housekeeping.
261 
262     NOTE: we should try to maintain block alignment of reads and writes to the
263     raw stream (according to the buffer size), but for now it is only done
264     in read() and friends.
265 
266 */
267 
268 /* These macros protect the buffered object against concurrent operations. */
269 
270 static int
_enter_buffered_busy(buffered * self)271 _enter_buffered_busy(buffered *self)
272 {
273     int relax_locking;
274     PyLockStatus st;
275     if (self->owner == PyThread_get_thread_ident()) {
276         PyErr_Format(PyExc_RuntimeError,
277                      "reentrant call inside %R", self);
278         return 0;
279     }
280     relax_locking = _Py_IsFinalizing();
281     Py_BEGIN_ALLOW_THREADS
282     if (!relax_locking)
283         st = PyThread_acquire_lock(self->lock, 1);
284     else {
285         /* When finalizing, we don't want a deadlock to happen with daemon
286          * threads abruptly shut down while they owned the lock.
287          * Therefore, only wait for a grace period (1 s.).
288          * Note that non-daemon threads have already exited here, so this
289          * shouldn't affect carefully written threaded I/O code.
290          */
291         st = PyThread_acquire_lock_timed(self->lock, (PY_TIMEOUT_T)1e6, 0);
292     }
293     Py_END_ALLOW_THREADS
294     if (relax_locking && st != PY_LOCK_ACQUIRED) {
295         PyObject *msgobj = PyUnicode_FromFormat(
296             "could not acquire lock for %A at interpreter "
297             "shutdown, possibly due to daemon threads",
298             (PyObject *) self);
299         const char *msg = PyUnicode_AsUTF8(msgobj);
300         Py_FatalError(msg);
301     }
302     return 1;
303 }
304 
305 #define ENTER_BUFFERED(self) \
306     ( (PyThread_acquire_lock(self->lock, 0) ? \
307        1 : _enter_buffered_busy(self)) \
308      && (self->owner = PyThread_get_thread_ident(), 1) )
309 
310 #define LEAVE_BUFFERED(self) \
311     do { \
312         self->owner = 0; \
313         PyThread_release_lock(self->lock); \
314     } while(0);
315 
316 #define CHECK_INITIALIZED(self) \
317     if (self->ok <= 0) { \
318         if (self->detached) { \
319             PyErr_SetString(PyExc_ValueError, \
320                  "raw stream has been detached"); \
321         } else { \
322             PyErr_SetString(PyExc_ValueError, \
323                 "I/O operation on uninitialized object"); \
324         } \
325         return NULL; \
326     }
327 
328 #define CHECK_INITIALIZED_INT(self) \
329     if (self->ok <= 0) { \
330         if (self->detached) { \
331             PyErr_SetString(PyExc_ValueError, \
332                  "raw stream has been detached"); \
333         } else { \
334             PyErr_SetString(PyExc_ValueError, \
335                 "I/O operation on uninitialized object"); \
336         } \
337         return -1; \
338     }
339 
340 #define IS_CLOSED(self) \
341     (!self->buffer || \
342     (self->fast_closed_checks \
343      ? _PyFileIO_closed(self->raw) \
344      : buffered_closed(self)))
345 
346 #define CHECK_CLOSED(self, error_msg) \
347     if (IS_CLOSED(self)) { \
348         PyErr_SetString(PyExc_ValueError, error_msg); \
349         return NULL; \
350     }
351 
352 
353 #define VALID_READ_BUFFER(self) \
354     (self->readable && self->read_end != -1)
355 
356 #define VALID_WRITE_BUFFER(self) \
357     (self->writable && self->write_end != -1)
358 
359 #define ADJUST_POSITION(self, _new_pos) \
360     do { \
361         self->pos = _new_pos; \
362         if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \
363             self->read_end = self->pos; \
364     } while(0)
365 
366 #define READAHEAD(self) \
367     ((self->readable && VALID_READ_BUFFER(self)) \
368         ? (self->read_end - self->pos) : 0)
369 
370 #define RAW_OFFSET(self) \
371     (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \
372         && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0)
373 
374 #define RAW_TELL(self) \
375     (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self))
376 
377 #define MINUS_LAST_BLOCK(self, size) \
378     (self->buffer_mask ? \
379         (size & ~self->buffer_mask) : \
380         (self->buffer_size * (size / self->buffer_size)))
381 
382 
383 static void
buffered_dealloc(buffered * self)384 buffered_dealloc(buffered *self)
385 {
386     self->finalizing = 1;
387     if (_PyIOBase_finalize((PyObject *) self) < 0)
388         return;
389     _PyObject_GC_UNTRACK(self);
390     self->ok = 0;
391     if (self->weakreflist != NULL)
392         PyObject_ClearWeakRefs((PyObject *)self);
393     Py_CLEAR(self->raw);
394     if (self->buffer) {
395         PyMem_Free(self->buffer);
396         self->buffer = NULL;
397     }
398     if (self->lock) {
399         PyThread_free_lock(self->lock);
400         self->lock = NULL;
401     }
402     Py_CLEAR(self->dict);
403     Py_TYPE(self)->tp_free((PyObject *)self);
404 }
405 
406 static PyObject *
buffered_sizeof(buffered * self,PyObject * Py_UNUSED (ignored))407 buffered_sizeof(buffered *self, PyObject *Py_UNUSED(ignored))
408 {
409     Py_ssize_t res;
410 
411     res = _PyObject_SIZE(Py_TYPE(self));
412     if (self->buffer)
413         res += self->buffer_size;
414     return PyLong_FromSsize_t(res);
415 }
416 
417 static int
buffered_traverse(buffered * self,visitproc visit,void * arg)418 buffered_traverse(buffered *self, visitproc visit, void *arg)
419 {
420     Py_VISIT(self->raw);
421     Py_VISIT(self->dict);
422     return 0;
423 }
424 
425 static int
buffered_clear(buffered * self)426 buffered_clear(buffered *self)
427 {
428     self->ok = 0;
429     Py_CLEAR(self->raw);
430     Py_CLEAR(self->dict);
431     return 0;
432 }
433 
434 /* Because this can call arbitrary code, it shouldn't be called when
435    the refcount is 0 (that is, not directly from tp_dealloc unless
436    the refcount has been temporarily re-incremented). */
437 static PyObject *
buffered_dealloc_warn(buffered * self,PyObject * source)438 buffered_dealloc_warn(buffered *self, PyObject *source)
439 {
440     if (self->ok && self->raw) {
441         PyObject *r;
442         r = _PyObject_CallMethodIdObjArgs(self->raw, &PyId__dealloc_warn,
443                                           source, NULL);
444         if (r)
445             Py_DECREF(r);
446         else
447             PyErr_Clear();
448     }
449     Py_RETURN_NONE;
450 }
451 
452 /*
453  * _BufferedIOMixin methods
454  * This is not a class, just a collection of methods that will be reused
455  * by BufferedReader and BufferedWriter
456  */
457 
458 /* Flush and close */
459 
460 static PyObject *
buffered_simple_flush(buffered * self,PyObject * args)461 buffered_simple_flush(buffered *self, PyObject *args)
462 {
463     CHECK_INITIALIZED(self)
464     return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL);
465 }
466 
467 static int
buffered_closed(buffered * self)468 buffered_closed(buffered *self)
469 {
470     int closed;
471     PyObject *res;
472     CHECK_INITIALIZED_INT(self)
473     res = PyObject_GetAttr(self->raw, _PyIO_str_closed);
474     if (res == NULL)
475         return -1;
476     closed = PyObject_IsTrue(res);
477     Py_DECREF(res);
478     return closed;
479 }
480 
481 static PyObject *
buffered_closed_get(buffered * self,void * context)482 buffered_closed_get(buffered *self, void *context)
483 {
484     CHECK_INITIALIZED(self)
485     return PyObject_GetAttr(self->raw, _PyIO_str_closed);
486 }
487 
488 static PyObject *
buffered_close(buffered * self,PyObject * args)489 buffered_close(buffered *self, PyObject *args)
490 {
491     PyObject *res = NULL, *exc = NULL, *val, *tb;
492     int r;
493 
494     CHECK_INITIALIZED(self)
495     if (!ENTER_BUFFERED(self))
496         return NULL;
497 
498     r = buffered_closed(self);
499     if (r < 0)
500         goto end;
501     if (r > 0) {
502         res = Py_None;
503         Py_INCREF(res);
504         goto end;
505     }
506 
507     if (self->finalizing) {
508         PyObject *r = buffered_dealloc_warn(self, (PyObject *) self);
509         if (r)
510             Py_DECREF(r);
511         else
512             PyErr_Clear();
513     }
514     /* flush() will most probably re-take the lock, so drop it first */
515     LEAVE_BUFFERED(self)
516     res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
517     if (!ENTER_BUFFERED(self))
518         return NULL;
519     if (res == NULL)
520         PyErr_Fetch(&exc, &val, &tb);
521     else
522         Py_DECREF(res);
523 
524     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL);
525 
526     if (self->buffer) {
527         PyMem_Free(self->buffer);
528         self->buffer = NULL;
529     }
530 
531     if (exc != NULL) {
532         _PyErr_ChainExceptions(exc, val, tb);
533         Py_CLEAR(res);
534     }
535 
536 end:
537     LEAVE_BUFFERED(self)
538     return res;
539 }
540 
541 /* detach */
542 
543 static PyObject *
buffered_detach(buffered * self,PyObject * Py_UNUSED (ignored))544 buffered_detach(buffered *self, PyObject *Py_UNUSED(ignored))
545 {
546     PyObject *raw, *res;
547     CHECK_INITIALIZED(self)
548     res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
549     if (res == NULL)
550         return NULL;
551     Py_DECREF(res);
552     raw = self->raw;
553     self->raw = NULL;
554     self->detached = 1;
555     self->ok = 0;
556     return raw;
557 }
558 
559 /* Inquiries */
560 
561 static PyObject *
buffered_seekable(buffered * self,PyObject * Py_UNUSED (ignored))562 buffered_seekable(buffered *self, PyObject *Py_UNUSED(ignored))
563 {
564     CHECK_INITIALIZED(self)
565     return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL);
566 }
567 
568 static PyObject *
buffered_readable(buffered * self,PyObject * Py_UNUSED (ignored))569 buffered_readable(buffered *self, PyObject *Py_UNUSED(ignored))
570 {
571     CHECK_INITIALIZED(self)
572     return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL);
573 }
574 
575 static PyObject *
buffered_writable(buffered * self,PyObject * Py_UNUSED (ignored))576 buffered_writable(buffered *self, PyObject *Py_UNUSED(ignored))
577 {
578     CHECK_INITIALIZED(self)
579     return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL);
580 }
581 
582 static PyObject *
buffered_name_get(buffered * self,void * context)583 buffered_name_get(buffered *self, void *context)
584 {
585     CHECK_INITIALIZED(self)
586     return _PyObject_GetAttrId(self->raw, &PyId_name);
587 }
588 
589 static PyObject *
buffered_mode_get(buffered * self,void * context)590 buffered_mode_get(buffered *self, void *context)
591 {
592     CHECK_INITIALIZED(self)
593     return _PyObject_GetAttrId(self->raw, &PyId_mode);
594 }
595 
596 /* Lower-level APIs */
597 
598 static PyObject *
buffered_fileno(buffered * self,PyObject * Py_UNUSED (ignored))599 buffered_fileno(buffered *self, PyObject *Py_UNUSED(ignored))
600 {
601     CHECK_INITIALIZED(self)
602     return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL);
603 }
604 
605 static PyObject *
buffered_isatty(buffered * self,PyObject * Py_UNUSED (ignored))606 buffered_isatty(buffered *self, PyObject *Py_UNUSED(ignored))
607 {
608     CHECK_INITIALIZED(self)
609     return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL);
610 }
611 
612 /* Forward decls */
613 static PyObject *
614 _bufferedwriter_flush_unlocked(buffered *);
615 static Py_ssize_t
616 _bufferedreader_fill_buffer(buffered *self);
617 static void
618 _bufferedreader_reset_buf(buffered *self);
619 static void
620 _bufferedwriter_reset_buf(buffered *self);
621 static PyObject *
622 _bufferedreader_peek_unlocked(buffered *self);
623 static PyObject *
624 _bufferedreader_read_all(buffered *self);
625 static PyObject *
626 _bufferedreader_read_fast(buffered *self, Py_ssize_t);
627 static PyObject *
628 _bufferedreader_read_generic(buffered *self, Py_ssize_t);
629 static Py_ssize_t
630 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len);
631 
632 /*
633  * Helpers
634  */
635 
636 /* Sets the current error to BlockingIOError */
637 static void
_set_BlockingIOError(const char * msg,Py_ssize_t written)638 _set_BlockingIOError(const char *msg, Py_ssize_t written)
639 {
640     PyObject *err;
641     PyErr_Clear();
642     err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
643                                 errno, msg, written);
644     if (err)
645         PyErr_SetObject(PyExc_BlockingIOError, err);
646     Py_XDECREF(err);
647 }
648 
649 /* Returns the address of the `written` member if a BlockingIOError was
650    raised, NULL otherwise. The error is always re-raised. */
651 static Py_ssize_t *
_buffered_check_blocking_error(void)652 _buffered_check_blocking_error(void)
653 {
654     PyObject *t, *v, *tb;
655     PyOSErrorObject *err;
656 
657     PyErr_Fetch(&t, &v, &tb);
658     if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) {
659         PyErr_Restore(t, v, tb);
660         return NULL;
661     }
662     err = (PyOSErrorObject *) v;
663     /* TODO: sanity check (err->written >= 0) */
664     PyErr_Restore(t, v, tb);
665     return &err->written;
666 }
667 
668 static Py_off_t
_buffered_raw_tell(buffered * self)669 _buffered_raw_tell(buffered *self)
670 {
671     Py_off_t n;
672     PyObject *res;
673     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL);
674     if (res == NULL)
675         return -1;
676     n = PyNumber_AsOff_t(res, PyExc_ValueError);
677     Py_DECREF(res);
678     if (n < 0) {
679         if (!PyErr_Occurred())
680             PyErr_Format(PyExc_OSError,
681                          "Raw stream returned invalid position %" PY_PRIdOFF,
682                          (PY_OFF_T_COMPAT)n);
683         return -1;
684     }
685     self->abs_pos = n;
686     return n;
687 }
688 
689 static Py_off_t
_buffered_raw_seek(buffered * self,Py_off_t target,int whence)690 _buffered_raw_seek(buffered *self, Py_off_t target, int whence)
691 {
692     PyObject *res, *posobj, *whenceobj;
693     Py_off_t n;
694 
695     posobj = PyLong_FromOff_t(target);
696     if (posobj == NULL)
697         return -1;
698     whenceobj = PyLong_FromLong(whence);
699     if (whenceobj == NULL) {
700         Py_DECREF(posobj);
701         return -1;
702     }
703     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek,
704                                      posobj, whenceobj, NULL);
705     Py_DECREF(posobj);
706     Py_DECREF(whenceobj);
707     if (res == NULL)
708         return -1;
709     n = PyNumber_AsOff_t(res, PyExc_ValueError);
710     Py_DECREF(res);
711     if (n < 0) {
712         if (!PyErr_Occurred())
713             PyErr_Format(PyExc_OSError,
714                          "Raw stream returned invalid position %" PY_PRIdOFF,
715                          (PY_OFF_T_COMPAT)n);
716         return -1;
717     }
718     self->abs_pos = n;
719     return n;
720 }
721 
722 static int
_buffered_init(buffered * self)723 _buffered_init(buffered *self)
724 {
725     Py_ssize_t n;
726     if (self->buffer_size <= 0) {
727         PyErr_SetString(PyExc_ValueError,
728             "buffer size must be strictly positive");
729         return -1;
730     }
731     if (self->buffer)
732         PyMem_Free(self->buffer);
733     self->buffer = PyMem_Malloc(self->buffer_size);
734     if (self->buffer == NULL) {
735         PyErr_NoMemory();
736         return -1;
737     }
738     if (self->lock)
739         PyThread_free_lock(self->lock);
740     self->lock = PyThread_allocate_lock();
741     if (self->lock == NULL) {
742         PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock");
743         return -1;
744     }
745     self->owner = 0;
746     /* Find out whether buffer_size is a power of 2 */
747     /* XXX is this optimization useful? */
748     for (n = self->buffer_size - 1; n & 1; n >>= 1)
749         ;
750     if (n == 0)
751         self->buffer_mask = self->buffer_size - 1;
752     else
753         self->buffer_mask = 0;
754     if (_buffered_raw_tell(self) == -1)
755         PyErr_Clear();
756     return 0;
757 }
758 
759 /* Return 1 if an OSError with errno == EINTR is set (and then
760    clears the error indicator), 0 otherwise.
761    Should only be called when PyErr_Occurred() is true.
762 */
763 int
_PyIO_trap_eintr(void)764 _PyIO_trap_eintr(void)
765 {
766     static PyObject *eintr_int = NULL;
767     PyObject *typ, *val, *tb;
768     PyOSErrorObject *env_err;
769 
770     if (eintr_int == NULL) {
771         eintr_int = PyLong_FromLong(EINTR);
772         assert(eintr_int != NULL);
773     }
774     if (!PyErr_ExceptionMatches(PyExc_OSError))
775         return 0;
776     PyErr_Fetch(&typ, &val, &tb);
777     PyErr_NormalizeException(&typ, &val, &tb);
778     env_err = (PyOSErrorObject *) val;
779     assert(env_err != NULL);
780     if (env_err->myerrno != NULL &&
781         PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) {
782         Py_DECREF(typ);
783         Py_DECREF(val);
784         Py_XDECREF(tb);
785         return 1;
786     }
787     /* This silences any error set by PyObject_RichCompareBool() */
788     PyErr_Restore(typ, val, tb);
789     return 0;
790 }
791 
792 /*
793  * Shared methods and wrappers
794  */
795 
796 static PyObject *
buffered_flush_and_rewind_unlocked(buffered * self)797 buffered_flush_and_rewind_unlocked(buffered *self)
798 {
799     PyObject *res;
800 
801     res = _bufferedwriter_flush_unlocked(self);
802     if (res == NULL)
803         return NULL;
804     Py_DECREF(res);
805 
806     if (self->readable) {
807         /* Rewind the raw stream so that its position corresponds to
808            the current logical position. */
809         Py_off_t n;
810         n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1);
811         _bufferedreader_reset_buf(self);
812         if (n == -1)
813             return NULL;
814     }
815     Py_RETURN_NONE;
816 }
817 
818 static PyObject *
buffered_flush(buffered * self,PyObject * args)819 buffered_flush(buffered *self, PyObject *args)
820 {
821     PyObject *res;
822 
823     CHECK_INITIALIZED(self)
824     CHECK_CLOSED(self, "flush of closed file")
825 
826     if (!ENTER_BUFFERED(self))
827         return NULL;
828     res = buffered_flush_and_rewind_unlocked(self);
829     LEAVE_BUFFERED(self)
830 
831     return res;
832 }
833 
834 /*[clinic input]
835 _io._Buffered.peek
836     size: Py_ssize_t = 0
837     /
838 
839 [clinic start generated code]*/
840 
841 static PyObject *
_io__Buffered_peek_impl(buffered * self,Py_ssize_t size)842 _io__Buffered_peek_impl(buffered *self, Py_ssize_t size)
843 /*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/
844 {
845     PyObject *res = NULL;
846 
847     CHECK_INITIALIZED(self)
848     CHECK_CLOSED(self, "peek of closed file")
849 
850     if (!ENTER_BUFFERED(self))
851         return NULL;
852 
853     if (self->writable) {
854         res = buffered_flush_and_rewind_unlocked(self);
855         if (res == NULL)
856             goto end;
857         Py_CLEAR(res);
858     }
859     res = _bufferedreader_peek_unlocked(self);
860 
861 end:
862     LEAVE_BUFFERED(self)
863     return res;
864 }
865 
866 /*[clinic input]
867 _io._Buffered.read
868     size as n: Py_ssize_t(accept={int, NoneType}) = -1
869     /
870 [clinic start generated code]*/
871 
872 static PyObject *
_io__Buffered_read_impl(buffered * self,Py_ssize_t n)873 _io__Buffered_read_impl(buffered *self, Py_ssize_t n)
874 /*[clinic end generated code: output=f41c78bb15b9bbe9 input=7df81e82e08a68a2]*/
875 {
876     PyObject *res;
877 
878     CHECK_INITIALIZED(self)
879     if (n < -1) {
880         PyErr_SetString(PyExc_ValueError,
881                         "read length must be non-negative or -1");
882         return NULL;
883     }
884 
885     CHECK_CLOSED(self, "read of closed file")
886 
887     if (n == -1) {
888         /* The number of bytes is unspecified, read until the end of stream */
889         if (!ENTER_BUFFERED(self))
890             return NULL;
891         res = _bufferedreader_read_all(self);
892     }
893     else {
894         res = _bufferedreader_read_fast(self, n);
895         if (res != Py_None)
896             return res;
897         Py_DECREF(res);
898         if (!ENTER_BUFFERED(self))
899             return NULL;
900         res = _bufferedreader_read_generic(self, n);
901     }
902 
903     LEAVE_BUFFERED(self)
904     return res;
905 }
906 
907 /*[clinic input]
908 _io._Buffered.read1
909     size as n: Py_ssize_t = -1
910     /
911 [clinic start generated code]*/
912 
913 static PyObject *
_io__Buffered_read1_impl(buffered * self,Py_ssize_t n)914 _io__Buffered_read1_impl(buffered *self, Py_ssize_t n)
915 /*[clinic end generated code: output=bcc4fb4e54d103a3 input=7d22de9630b61774]*/
916 {
917     Py_ssize_t have, r;
918     PyObject *res = NULL;
919 
920     CHECK_INITIALIZED(self)
921     if (n < 0) {
922         n = self->buffer_size;
923     }
924 
925     CHECK_CLOSED(self, "read of closed file")
926 
927     if (n == 0)
928         return PyBytes_FromStringAndSize(NULL, 0);
929 
930     /* Return up to n bytes.  If at least one byte is buffered, we
931        only return buffered bytes.  Otherwise, we do one raw read. */
932 
933     have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
934     if (have > 0) {
935         n = Py_MIN(have, n);
936         res = _bufferedreader_read_fast(self, n);
937         assert(res != Py_None);
938         return res;
939     }
940     res = PyBytes_FromStringAndSize(NULL, n);
941     if (res == NULL)
942         return NULL;
943     if (!ENTER_BUFFERED(self)) {
944         Py_DECREF(res);
945         return NULL;
946     }
947     _bufferedreader_reset_buf(self);
948     r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n);
949     LEAVE_BUFFERED(self)
950     if (r == -1) {
951         Py_DECREF(res);
952         return NULL;
953     }
954     if (r == -2)
955         r = 0;
956     if (n > r)
957         _PyBytes_Resize(&res, r);
958     return res;
959 }
960 
961 static PyObject *
_buffered_readinto_generic(buffered * self,Py_buffer * buffer,char readinto1)962 _buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1)
963 {
964     Py_ssize_t n, written = 0, remaining;
965     PyObject *res = NULL;
966 
967     CHECK_INITIALIZED(self)
968     CHECK_CLOSED(self, "readinto of closed file")
969 
970     n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
971     if (n > 0) {
972         if (n >= buffer->len) {
973             memcpy(buffer->buf, self->buffer + self->pos, buffer->len);
974             self->pos += buffer->len;
975             return PyLong_FromSsize_t(buffer->len);
976         }
977         memcpy(buffer->buf, self->buffer + self->pos, n);
978         self->pos += n;
979         written = n;
980     }
981 
982     if (!ENTER_BUFFERED(self))
983         return NULL;
984 
985     if (self->writable) {
986         res = buffered_flush_and_rewind_unlocked(self);
987         if (res == NULL)
988             goto end;
989         Py_CLEAR(res);
990     }
991 
992     _bufferedreader_reset_buf(self);
993     self->pos = 0;
994 
995     for (remaining = buffer->len - written;
996          remaining > 0;
997          written += n, remaining -= n) {
998         /* If remaining bytes is larger than internal buffer size, copy
999          * directly into caller's buffer. */
1000         if (remaining > self->buffer_size) {
1001             n = _bufferedreader_raw_read(self, (char *) buffer->buf + written,
1002                                          remaining);
1003         }
1004 
1005         /* In readinto1 mode, we do not want to fill the internal
1006            buffer if we already have some data to return */
1007         else if (!(readinto1 && written)) {
1008             n = _bufferedreader_fill_buffer(self);
1009             if (n > 0) {
1010                 if (n > remaining)
1011                     n = remaining;
1012                 memcpy((char *) buffer->buf + written,
1013                        self->buffer + self->pos, n);
1014                 self->pos += n;
1015                 continue; /* short circuit */
1016             }
1017         }
1018         else
1019             n = 0;
1020 
1021         if (n == 0 || (n == -2 && written > 0))
1022             break;
1023         if (n < 0) {
1024             if (n == -2) {
1025                 Py_INCREF(Py_None);
1026                 res = Py_None;
1027             }
1028             goto end;
1029         }
1030 
1031         /* At most one read in readinto1 mode */
1032         if (readinto1) {
1033             written += n;
1034             break;
1035         }
1036     }
1037     res = PyLong_FromSsize_t(written);
1038 
1039 end:
1040     LEAVE_BUFFERED(self);
1041     return res;
1042 }
1043 
1044 /*[clinic input]
1045 _io._Buffered.readinto
1046     buffer: Py_buffer(accept={rwbuffer})
1047     /
1048 [clinic start generated code]*/
1049 
1050 static PyObject *
_io__Buffered_readinto_impl(buffered * self,Py_buffer * buffer)1051 _io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer)
1052 /*[clinic end generated code: output=bcb376580b1d8170 input=ed6b98b7a20a3008]*/
1053 {
1054     return _buffered_readinto_generic(self, buffer, 0);
1055 }
1056 
1057 /*[clinic input]
1058 _io._Buffered.readinto1
1059     buffer: Py_buffer(accept={rwbuffer})
1060     /
1061 [clinic start generated code]*/
1062 
1063 static PyObject *
_io__Buffered_readinto1_impl(buffered * self,Py_buffer * buffer)1064 _io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer)
1065 /*[clinic end generated code: output=6e5c6ac5868205d6 input=4455c5d55fdf1687]*/
1066 {
1067     return _buffered_readinto_generic(self, buffer, 1);
1068 }
1069 
1070 
1071 static PyObject *
_buffered_readline(buffered * self,Py_ssize_t limit)1072 _buffered_readline(buffered *self, Py_ssize_t limit)
1073 {
1074     PyObject *res = NULL;
1075     PyObject *chunks = NULL;
1076     Py_ssize_t n, written = 0;
1077     const char *start, *s, *end;
1078 
1079     CHECK_CLOSED(self, "readline of closed file")
1080 
1081     /* First, try to find a line in the buffer. This can run unlocked because
1082        the calls to the C API are simple enough that they can't trigger
1083        any thread switch. */
1084     n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1085     if (limit >= 0 && n > limit)
1086         n = limit;
1087     start = self->buffer + self->pos;
1088     s = memchr(start, '\n', n);
1089     if (s != NULL) {
1090         res = PyBytes_FromStringAndSize(start, s - start + 1);
1091         if (res != NULL)
1092             self->pos += s - start + 1;
1093         goto end_unlocked;
1094     }
1095     if (n == limit) {
1096         res = PyBytes_FromStringAndSize(start, n);
1097         if (res != NULL)
1098             self->pos += n;
1099         goto end_unlocked;
1100     }
1101 
1102     if (!ENTER_BUFFERED(self))
1103         goto end_unlocked;
1104 
1105     /* Now we try to get some more from the raw stream */
1106     chunks = PyList_New(0);
1107     if (chunks == NULL)
1108         goto end;
1109     if (n > 0) {
1110         res = PyBytes_FromStringAndSize(start, n);
1111         if (res == NULL)
1112             goto end;
1113         if (PyList_Append(chunks, res) < 0) {
1114             Py_CLEAR(res);
1115             goto end;
1116         }
1117         Py_CLEAR(res);
1118         written += n;
1119         self->pos += n;
1120         if (limit >= 0)
1121             limit -= n;
1122     }
1123     if (self->writable) {
1124         PyObject *r = buffered_flush_and_rewind_unlocked(self);
1125         if (r == NULL)
1126             goto end;
1127         Py_DECREF(r);
1128     }
1129 
1130     for (;;) {
1131         _bufferedreader_reset_buf(self);
1132         n = _bufferedreader_fill_buffer(self);
1133         if (n == -1)
1134             goto end;
1135         if (n <= 0)
1136             break;
1137         if (limit >= 0 && n > limit)
1138             n = limit;
1139         start = self->buffer;
1140         end = start + n;
1141         s = start;
1142         while (s < end) {
1143             if (*s++ == '\n') {
1144                 res = PyBytes_FromStringAndSize(start, s - start);
1145                 if (res == NULL)
1146                     goto end;
1147                 self->pos = s - start;
1148                 goto found;
1149             }
1150         }
1151         res = PyBytes_FromStringAndSize(start, n);
1152         if (res == NULL)
1153             goto end;
1154         if (n == limit) {
1155             self->pos = n;
1156             break;
1157         }
1158         if (PyList_Append(chunks, res) < 0) {
1159             Py_CLEAR(res);
1160             goto end;
1161         }
1162         Py_CLEAR(res);
1163         written += n;
1164         if (limit >= 0)
1165             limit -= n;
1166     }
1167 found:
1168     if (res != NULL && PyList_Append(chunks, res) < 0) {
1169         Py_CLEAR(res);
1170         goto end;
1171     }
1172     Py_XSETREF(res, _PyBytes_Join(_PyIO_empty_bytes, chunks));
1173 
1174 end:
1175     LEAVE_BUFFERED(self)
1176 end_unlocked:
1177     Py_XDECREF(chunks);
1178     return res;
1179 }
1180 
1181 /*[clinic input]
1182 _io._Buffered.readline
1183     size: Py_ssize_t(accept={int, NoneType}) = -1
1184     /
1185 [clinic start generated code]*/
1186 
1187 static PyObject *
_io__Buffered_readline_impl(buffered * self,Py_ssize_t size)1188 _io__Buffered_readline_impl(buffered *self, Py_ssize_t size)
1189 /*[clinic end generated code: output=24dd2aa6e33be83c input=673b6240e315ef8a]*/
1190 {
1191     CHECK_INITIALIZED(self)
1192     return _buffered_readline(self, size);
1193 }
1194 
1195 
1196 static PyObject *
buffered_tell(buffered * self,PyObject * Py_UNUSED (ignored))1197 buffered_tell(buffered *self, PyObject *Py_UNUSED(ignored))
1198 {
1199     Py_off_t pos;
1200 
1201     CHECK_INITIALIZED(self)
1202     pos = _buffered_raw_tell(self);
1203     if (pos == -1)
1204         return NULL;
1205     pos -= RAW_OFFSET(self);
1206     /* TODO: sanity check (pos >= 0) */
1207     return PyLong_FromOff_t(pos);
1208 }
1209 
1210 /*[clinic input]
1211 _io._Buffered.seek
1212     target as targetobj: object
1213     whence: int = 0
1214     /
1215 [clinic start generated code]*/
1216 
1217 static PyObject *
_io__Buffered_seek_impl(buffered * self,PyObject * targetobj,int whence)1218 _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
1219 /*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/
1220 {
1221     Py_off_t target, n;
1222     PyObject *res = NULL;
1223 
1224     CHECK_INITIALIZED(self)
1225 
1226     /* Do some error checking instead of trusting OS 'seek()'
1227     ** error detection, just in case.
1228     */
1229     if ((whence < 0 || whence >2)
1230 #ifdef SEEK_HOLE
1231         && (whence != SEEK_HOLE)
1232 #endif
1233 #ifdef SEEK_DATA
1234         && (whence != SEEK_DATA)
1235 #endif
1236         ) {
1237         PyErr_Format(PyExc_ValueError,
1238                      "whence value %d unsupported", whence);
1239         return NULL;
1240     }
1241 
1242     CHECK_CLOSED(self, "seek of closed file")
1243 
1244     if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL)
1245         return NULL;
1246 
1247     target = PyNumber_AsOff_t(targetobj, PyExc_ValueError);
1248     if (target == -1 && PyErr_Occurred())
1249         return NULL;
1250 
1251     /* SEEK_SET and SEEK_CUR are special because we could seek inside the
1252        buffer. Other whence values must be managed without this optimization.
1253        Some Operating Systems can provide additional values, like
1254        SEEK_HOLE/SEEK_DATA. */
1255     if (((whence == 0) || (whence == 1)) && self->readable) {
1256         Py_off_t current, avail;
1257         /* Check if seeking leaves us inside the current buffer,
1258            so as to return quickly if possible. Also, we needn't take the
1259            lock in this fast path.
1260            Don't know how to do that when whence == 2, though. */
1261         /* NOTE: RAW_TELL() can release the GIL but the object is in a stable
1262            state at this point. */
1263         current = RAW_TELL(self);
1264         avail = READAHEAD(self);
1265         if (avail > 0) {
1266             Py_off_t offset;
1267             if (whence == 0)
1268                 offset = target - (current - RAW_OFFSET(self));
1269             else
1270                 offset = target;
1271             if (offset >= -self->pos && offset <= avail) {
1272                 self->pos += offset;
1273                 return PyLong_FromOff_t(current - avail + offset);
1274             }
1275         }
1276     }
1277 
1278     if (!ENTER_BUFFERED(self))
1279         return NULL;
1280 
1281     /* Fallback: invoke raw seek() method and clear buffer */
1282     if (self->writable) {
1283         res = _bufferedwriter_flush_unlocked(self);
1284         if (res == NULL)
1285             goto end;
1286         Py_CLEAR(res);
1287     }
1288 
1289     /* TODO: align on block boundary and read buffer if needed? */
1290     if (whence == 1)
1291         target -= RAW_OFFSET(self);
1292     n = _buffered_raw_seek(self, target, whence);
1293     if (n == -1)
1294         goto end;
1295     self->raw_pos = -1;
1296     res = PyLong_FromOff_t(n);
1297     if (res != NULL && self->readable)
1298         _bufferedreader_reset_buf(self);
1299 
1300 end:
1301     LEAVE_BUFFERED(self)
1302     return res;
1303 }
1304 
1305 /*[clinic input]
1306 _io._Buffered.truncate
1307     pos: object = None
1308     /
1309 [clinic start generated code]*/
1310 
1311 static PyObject *
_io__Buffered_truncate_impl(buffered * self,PyObject * pos)1312 _io__Buffered_truncate_impl(buffered *self, PyObject *pos)
1313 /*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/
1314 {
1315     PyObject *res = NULL;
1316 
1317     CHECK_INITIALIZED(self)
1318     if (!ENTER_BUFFERED(self))
1319         return NULL;
1320 
1321     if (self->writable) {
1322         res = buffered_flush_and_rewind_unlocked(self);
1323         if (res == NULL)
1324             goto end;
1325         Py_CLEAR(res);
1326     }
1327     res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL);
1328     if (res == NULL)
1329         goto end;
1330     /* Reset cached position */
1331     if (_buffered_raw_tell(self) == -1)
1332         PyErr_Clear();
1333 
1334 end:
1335     LEAVE_BUFFERED(self)
1336     return res;
1337 }
1338 
1339 static PyObject *
buffered_iternext(buffered * self)1340 buffered_iternext(buffered *self)
1341 {
1342     PyObject *line;
1343     PyTypeObject *tp;
1344 
1345     CHECK_INITIALIZED(self);
1346 
1347     tp = Py_TYPE(self);
1348     if (tp == &PyBufferedReader_Type ||
1349         tp == &PyBufferedRandom_Type) {
1350         /* Skip method call overhead for speed */
1351         line = _buffered_readline(self, -1);
1352     }
1353     else {
1354         line = PyObject_CallMethodObjArgs((PyObject *)self,
1355                                            _PyIO_str_readline, NULL);
1356         if (line && !PyBytes_Check(line)) {
1357             PyErr_Format(PyExc_OSError,
1358                          "readline() should have returned a bytes object, "
1359                          "not '%.200s'", Py_TYPE(line)->tp_name);
1360             Py_DECREF(line);
1361             return NULL;
1362         }
1363     }
1364 
1365     if (line == NULL)
1366         return NULL;
1367 
1368     if (PyBytes_GET_SIZE(line) == 0) {
1369         /* Reached EOF or would have blocked */
1370         Py_DECREF(line);
1371         return NULL;
1372     }
1373 
1374     return line;
1375 }
1376 
1377 static PyObject *
buffered_repr(buffered * self)1378 buffered_repr(buffered *self)
1379 {
1380     PyObject *nameobj, *res;
1381 
1382     if (_PyObject_LookupAttrId((PyObject *) self, &PyId_name, &nameobj) < 0) {
1383         if (!PyErr_ExceptionMatches(PyExc_ValueError)) {
1384             return NULL;
1385         }
1386         /* Ignore ValueError raised if the underlying stream was detached */
1387         PyErr_Clear();
1388     }
1389     if (nameobj == NULL) {
1390         res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
1391     }
1392     else {
1393         int status = Py_ReprEnter((PyObject *)self);
1394         res = NULL;
1395         if (status == 0) {
1396             res = PyUnicode_FromFormat("<%s name=%R>",
1397                                        Py_TYPE(self)->tp_name, nameobj);
1398             Py_ReprLeave((PyObject *)self);
1399         }
1400         else if (status > 0) {
1401             PyErr_Format(PyExc_RuntimeError,
1402                          "reentrant call inside %s.__repr__",
1403                          Py_TYPE(self)->tp_name);
1404         }
1405         Py_DECREF(nameobj);
1406     }
1407     return res;
1408 }
1409 
1410 /*
1411  * class BufferedReader
1412  */
1413 
_bufferedreader_reset_buf(buffered * self)1414 static void _bufferedreader_reset_buf(buffered *self)
1415 {
1416     self->read_end = -1;
1417 }
1418 
1419 /*[clinic input]
1420 _io.BufferedReader.__init__
1421     raw: object
1422     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1423 
1424 Create a new buffered reader using the given readable raw IO object.
1425 [clinic start generated code]*/
1426 
1427 static int
_io_BufferedReader___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1428 _io_BufferedReader___init___impl(buffered *self, PyObject *raw,
1429                                  Py_ssize_t buffer_size)
1430 /*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/
1431 {
1432     self->ok = 0;
1433     self->detached = 0;
1434 
1435     if (_PyIOBase_check_readable(raw, Py_True) == NULL)
1436         return -1;
1437 
1438     Py_INCREF(raw);
1439     Py_XSETREF(self->raw, raw);
1440     self->buffer_size = buffer_size;
1441     self->readable = 1;
1442     self->writable = 0;
1443 
1444     if (_buffered_init(self) < 0)
1445         return -1;
1446     _bufferedreader_reset_buf(self);
1447 
1448     self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type &&
1449                                 Py_TYPE(raw) == &PyFileIO_Type);
1450 
1451     self->ok = 1;
1452     return 0;
1453 }
1454 
1455 static Py_ssize_t
_bufferedreader_raw_read(buffered * self,char * start,Py_ssize_t len)1456 _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len)
1457 {
1458     Py_buffer buf;
1459     PyObject *memobj, *res;
1460     Py_ssize_t n;
1461     /* NOTE: the buffer needn't be released as its object is NULL. */
1462     if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1)
1463         return -1;
1464     memobj = PyMemoryView_FromBuffer(&buf);
1465     if (memobj == NULL)
1466         return -1;
1467     /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1468        occurs so we needn't do it ourselves.
1469        We then retry reading, ignoring the signal if no handler has
1470        raised (see issue #10956).
1471     */
1472     do {
1473         res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL);
1474     } while (res == NULL && _PyIO_trap_eintr());
1475     Py_DECREF(memobj);
1476     if (res == NULL)
1477         return -1;
1478     if (res == Py_None) {
1479         /* Non-blocking stream would have blocked. Special return code! */
1480         Py_DECREF(res);
1481         return -2;
1482     }
1483     n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1484     Py_DECREF(res);
1485     if (n < 0 || n > len) {
1486         PyErr_Format(PyExc_OSError,
1487                      "raw readinto() returned invalid length %zd "
1488                      "(should have been between 0 and %zd)", n, len);
1489         return -1;
1490     }
1491     if (n > 0 && self->abs_pos != -1)
1492         self->abs_pos += n;
1493     return n;
1494 }
1495 
1496 static Py_ssize_t
_bufferedreader_fill_buffer(buffered * self)1497 _bufferedreader_fill_buffer(buffered *self)
1498 {
1499     Py_ssize_t start, len, n;
1500     if (VALID_READ_BUFFER(self))
1501         start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t);
1502     else
1503         start = 0;
1504     len = self->buffer_size - start;
1505     n = _bufferedreader_raw_read(self, self->buffer + start, len);
1506     if (n <= 0)
1507         return n;
1508     self->read_end = start + n;
1509     self->raw_pos = start + n;
1510     return n;
1511 }
1512 
1513 static PyObject *
_bufferedreader_read_all(buffered * self)1514 _bufferedreader_read_all(buffered *self)
1515 {
1516     Py_ssize_t current_size;
1517     PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL, *readall;
1518 
1519     /* First copy what we have in the current buffer. */
1520     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1521     if (current_size) {
1522         data = PyBytes_FromStringAndSize(
1523             self->buffer + self->pos, current_size);
1524         if (data == NULL)
1525             return NULL;
1526         self->pos += current_size;
1527     }
1528     /* We're going past the buffer's bounds, flush it */
1529     if (self->writable) {
1530         tmp = buffered_flush_and_rewind_unlocked(self);
1531         if (tmp == NULL)
1532             goto cleanup;
1533         Py_CLEAR(tmp);
1534     }
1535     _bufferedreader_reset_buf(self);
1536 
1537     if (_PyObject_LookupAttr(self->raw, _PyIO_str_readall, &readall) < 0) {
1538         goto cleanup;
1539     }
1540     if (readall) {
1541         tmp = _PyObject_CallNoArg(readall);
1542         Py_DECREF(readall);
1543         if (tmp == NULL)
1544             goto cleanup;
1545         if (tmp != Py_None && !PyBytes_Check(tmp)) {
1546             PyErr_SetString(PyExc_TypeError, "readall() should return bytes");
1547             goto cleanup;
1548         }
1549         if (current_size == 0) {
1550             res = tmp;
1551         } else {
1552             if (tmp != Py_None) {
1553                 PyBytes_Concat(&data, tmp);
1554             }
1555             res = data;
1556         }
1557         goto cleanup;
1558     }
1559 
1560     chunks = PyList_New(0);
1561     if (chunks == NULL)
1562         goto cleanup;
1563 
1564     while (1) {
1565         if (data) {
1566             if (PyList_Append(chunks, data) < 0)
1567                 goto cleanup;
1568             Py_CLEAR(data);
1569         }
1570 
1571         /* Read until EOF or until read() would block. */
1572         data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL);
1573         if (data == NULL)
1574             goto cleanup;
1575         if (data != Py_None && !PyBytes_Check(data)) {
1576             PyErr_SetString(PyExc_TypeError, "read() should return bytes");
1577             goto cleanup;
1578         }
1579         if (data == Py_None || PyBytes_GET_SIZE(data) == 0) {
1580             if (current_size == 0) {
1581                 res = data;
1582                 goto cleanup;
1583             }
1584             else {
1585                 tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks);
1586                 res = tmp;
1587                 goto cleanup;
1588             }
1589         }
1590         current_size += PyBytes_GET_SIZE(data);
1591         if (self->abs_pos != -1)
1592             self->abs_pos += PyBytes_GET_SIZE(data);
1593     }
1594 cleanup:
1595     /* res is either NULL or a borrowed ref */
1596     Py_XINCREF(res);
1597     Py_XDECREF(data);
1598     Py_XDECREF(tmp);
1599     Py_XDECREF(chunks);
1600     return res;
1601 }
1602 
1603 /* Read n bytes from the buffer if it can, otherwise return None.
1604    This function is simple enough that it can run unlocked. */
1605 static PyObject *
_bufferedreader_read_fast(buffered * self,Py_ssize_t n)1606 _bufferedreader_read_fast(buffered *self, Py_ssize_t n)
1607 {
1608     Py_ssize_t current_size;
1609 
1610     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1611     if (n <= current_size) {
1612         /* Fast path: the data to read is fully buffered. */
1613         PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n);
1614         if (res != NULL)
1615             self->pos += n;
1616         return res;
1617     }
1618     Py_RETURN_NONE;
1619 }
1620 
1621 /* Generic read function: read from the stream until enough bytes are read,
1622  * or until an EOF occurs or until read() would block.
1623  */
1624 static PyObject *
_bufferedreader_read_generic(buffered * self,Py_ssize_t n)1625 _bufferedreader_read_generic(buffered *self, Py_ssize_t n)
1626 {
1627     PyObject *res = NULL;
1628     Py_ssize_t current_size, remaining, written;
1629     char *out;
1630 
1631     current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1632     if (n <= current_size)
1633         return _bufferedreader_read_fast(self, n);
1634 
1635     res = PyBytes_FromStringAndSize(NULL, n);
1636     if (res == NULL)
1637         goto error;
1638     out = PyBytes_AS_STRING(res);
1639     remaining = n;
1640     written = 0;
1641     if (current_size > 0) {
1642         memcpy(out, self->buffer + self->pos, current_size);
1643         remaining -= current_size;
1644         written += current_size;
1645         self->pos += current_size;
1646     }
1647     /* Flush the write buffer if necessary */
1648     if (self->writable) {
1649         PyObject *r = buffered_flush_and_rewind_unlocked(self);
1650         if (r == NULL)
1651             goto error;
1652         Py_DECREF(r);
1653     }
1654     _bufferedreader_reset_buf(self);
1655     while (remaining > 0) {
1656         /* We want to read a whole block at the end into buffer.
1657            If we had readv() we could do this in one pass. */
1658         Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining);
1659         if (r == 0)
1660             break;
1661         r = _bufferedreader_raw_read(self, out + written, r);
1662         if (r == -1)
1663             goto error;
1664         if (r == 0 || r == -2) {
1665             /* EOF occurred or read() would block. */
1666             if (r == 0 || written > 0) {
1667                 if (_PyBytes_Resize(&res, written))
1668                     goto error;
1669                 return res;
1670             }
1671             Py_DECREF(res);
1672             Py_RETURN_NONE;
1673         }
1674         remaining -= r;
1675         written += r;
1676     }
1677     assert(remaining <= self->buffer_size);
1678     self->pos = 0;
1679     self->raw_pos = 0;
1680     self->read_end = 0;
1681     /* NOTE: when the read is satisfied, we avoid issuing any additional
1682        reads, which could block indefinitely (e.g. on a socket).
1683        See issue #9550. */
1684     while (remaining > 0 && self->read_end < self->buffer_size) {
1685         Py_ssize_t r = _bufferedreader_fill_buffer(self);
1686         if (r == -1)
1687             goto error;
1688         if (r == 0 || r == -2) {
1689             /* EOF occurred or read() would block. */
1690             if (r == 0 || written > 0) {
1691                 if (_PyBytes_Resize(&res, written))
1692                     goto error;
1693                 return res;
1694             }
1695             Py_DECREF(res);
1696             Py_RETURN_NONE;
1697         }
1698         if (remaining > r) {
1699             memcpy(out + written, self->buffer + self->pos, r);
1700             written += r;
1701             self->pos += r;
1702             remaining -= r;
1703         }
1704         else if (remaining > 0) {
1705             memcpy(out + written, self->buffer + self->pos, remaining);
1706             written += remaining;
1707             self->pos += remaining;
1708             remaining = 0;
1709         }
1710         if (remaining == 0)
1711             break;
1712     }
1713 
1714     return res;
1715 
1716 error:
1717     Py_XDECREF(res);
1718     return NULL;
1719 }
1720 
1721 static PyObject *
_bufferedreader_peek_unlocked(buffered * self)1722 _bufferedreader_peek_unlocked(buffered *self)
1723 {
1724     Py_ssize_t have, r;
1725 
1726     have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t);
1727     /* Constraints:
1728        1. we don't want to advance the file position.
1729        2. we don't want to lose block alignment, so we can't shift the buffer
1730           to make some place.
1731        Therefore, we either return `have` bytes (if > 0), or a full buffer.
1732     */
1733     if (have > 0) {
1734         return PyBytes_FromStringAndSize(self->buffer + self->pos, have);
1735     }
1736 
1737     /* Fill the buffer from the raw stream, and copy it to the result. */
1738     _bufferedreader_reset_buf(self);
1739     r = _bufferedreader_fill_buffer(self);
1740     if (r == -1)
1741         return NULL;
1742     if (r == -2)
1743         r = 0;
1744     self->pos = 0;
1745     return PyBytes_FromStringAndSize(self->buffer, r);
1746 }
1747 
1748 
1749 
1750 /*
1751  * class BufferedWriter
1752  */
1753 static void
_bufferedwriter_reset_buf(buffered * self)1754 _bufferedwriter_reset_buf(buffered *self)
1755 {
1756     self->write_pos = 0;
1757     self->write_end = -1;
1758 }
1759 
1760 /*[clinic input]
1761 _io.BufferedWriter.__init__
1762     raw: object
1763     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
1764 
1765 A buffer for a writeable sequential RawIO object.
1766 
1767 The constructor creates a BufferedWriter for the given writeable raw
1768 stream. If the buffer_size is not given, it defaults to
1769 DEFAULT_BUFFER_SIZE.
1770 [clinic start generated code]*/
1771 
1772 static int
_io_BufferedWriter___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)1773 _io_BufferedWriter___init___impl(buffered *self, PyObject *raw,
1774                                  Py_ssize_t buffer_size)
1775 /*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/
1776 {
1777     self->ok = 0;
1778     self->detached = 0;
1779 
1780     if (_PyIOBase_check_writable(raw, Py_True) == NULL)
1781         return -1;
1782 
1783     Py_INCREF(raw);
1784     Py_XSETREF(self->raw, raw);
1785     self->readable = 0;
1786     self->writable = 1;
1787 
1788     self->buffer_size = buffer_size;
1789     if (_buffered_init(self) < 0)
1790         return -1;
1791     _bufferedwriter_reset_buf(self);
1792     self->pos = 0;
1793 
1794     self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type &&
1795                                 Py_TYPE(raw) == &PyFileIO_Type);
1796 
1797     self->ok = 1;
1798     return 0;
1799 }
1800 
1801 static Py_ssize_t
_bufferedwriter_raw_write(buffered * self,char * start,Py_ssize_t len)1802 _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
1803 {
1804     Py_buffer buf;
1805     PyObject *memobj, *res;
1806     Py_ssize_t n;
1807     int errnum;
1808     /* NOTE: the buffer needn't be released as its object is NULL. */
1809     if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1)
1810         return -1;
1811     memobj = PyMemoryView_FromBuffer(&buf);
1812     if (memobj == NULL)
1813         return -1;
1814     /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR
1815        occurs so we needn't do it ourselves.
1816        We then retry writing, ignoring the signal if no handler has
1817        raised (see issue #10956).
1818     */
1819     do {
1820         errno = 0;
1821         res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL);
1822         errnum = errno;
1823     } while (res == NULL && _PyIO_trap_eintr());
1824     Py_DECREF(memobj);
1825     if (res == NULL)
1826         return -1;
1827     if (res == Py_None) {
1828         /* Non-blocking stream would have blocked. Special return code!
1829            Being paranoid we reset errno in case it is changed by code
1830            triggered by a decref.  errno is used by _set_BlockingIOError(). */
1831         Py_DECREF(res);
1832         errno = errnum;
1833         return -2;
1834     }
1835     n = PyNumber_AsSsize_t(res, PyExc_ValueError);
1836     Py_DECREF(res);
1837     if (n < 0 || n > len) {
1838         PyErr_Format(PyExc_OSError,
1839                      "raw write() returned invalid length %zd "
1840                      "(should have been between 0 and %zd)", n, len);
1841         return -1;
1842     }
1843     if (n > 0 && self->abs_pos != -1)
1844         self->abs_pos += n;
1845     return n;
1846 }
1847 
1848 static PyObject *
_bufferedwriter_flush_unlocked(buffered * self)1849 _bufferedwriter_flush_unlocked(buffered *self)
1850 {
1851     Py_ssize_t written = 0;
1852     Py_off_t n, rewind;
1853 
1854     if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end)
1855         goto end;
1856     /* First, rewind */
1857     rewind = RAW_OFFSET(self) + (self->pos - self->write_pos);
1858     if (rewind != 0) {
1859         n = _buffered_raw_seek(self, -rewind, 1);
1860         if (n < 0) {
1861             goto error;
1862         }
1863         self->raw_pos -= rewind;
1864     }
1865     while (self->write_pos < self->write_end) {
1866         n = _bufferedwriter_raw_write(self,
1867             self->buffer + self->write_pos,
1868             Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1869                              Py_off_t, Py_ssize_t));
1870         if (n == -1) {
1871             goto error;
1872         }
1873         else if (n == -2) {
1874             _set_BlockingIOError("write could not complete without blocking",
1875                                  0);
1876             goto error;
1877         }
1878         self->write_pos += n;
1879         self->raw_pos = self->write_pos;
1880         written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t);
1881         /* Partial writes can return successfully when interrupted by a
1882            signal (see write(2)).  We must run signal handlers before
1883            blocking another time, possibly indefinitely. */
1884         if (PyErr_CheckSignals() < 0)
1885             goto error;
1886     }
1887 
1888 
1889 end:
1890     /* This ensures that after return from this function,
1891        VALID_WRITE_BUFFER(self) returns false.
1892 
1893        This is a required condition because when a tell() is called
1894        after flushing and if VALID_READ_BUFFER(self) is false, we need
1895        VALID_WRITE_BUFFER(self) to be false to have
1896        RAW_OFFSET(self) == 0.
1897 
1898        Issue: https://bugs.python.org/issue32228 */
1899     _bufferedwriter_reset_buf(self);
1900     Py_RETURN_NONE;
1901 
1902 error:
1903     return NULL;
1904 }
1905 
1906 /*[clinic input]
1907 _io.BufferedWriter.write
1908     buffer: Py_buffer
1909     /
1910 [clinic start generated code]*/
1911 
1912 static PyObject *
_io_BufferedWriter_write_impl(buffered * self,Py_buffer * buffer)1913 _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
1914 /*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/
1915 {
1916     PyObject *res = NULL;
1917     Py_ssize_t written, avail, remaining;
1918     Py_off_t offset;
1919 
1920     CHECK_INITIALIZED(self)
1921 
1922     if (!ENTER_BUFFERED(self))
1923         return NULL;
1924 
1925     /* Issue #31976: Check for closed file after acquiring the lock. Another
1926        thread could be holding the lock while closing the file. */
1927     if (IS_CLOSED(self)) {
1928         PyErr_SetString(PyExc_ValueError, "write to closed file");
1929         goto error;
1930     }
1931 
1932     /* Fast path: the data to write can be fully buffered. */
1933     if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) {
1934         self->pos = 0;
1935         self->raw_pos = 0;
1936     }
1937     avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t);
1938     if (buffer->len <= avail) {
1939         memcpy(self->buffer + self->pos, buffer->buf, buffer->len);
1940         if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) {
1941             self->write_pos = self->pos;
1942         }
1943         ADJUST_POSITION(self, self->pos + buffer->len);
1944         if (self->pos > self->write_end)
1945             self->write_end = self->pos;
1946         written = buffer->len;
1947         goto end;
1948     }
1949 
1950     /* First write the current buffer */
1951     res = _bufferedwriter_flush_unlocked(self);
1952     if (res == NULL) {
1953         Py_ssize_t *w = _buffered_check_blocking_error();
1954         if (w == NULL)
1955             goto error;
1956         if (self->readable)
1957             _bufferedreader_reset_buf(self);
1958         /* Make some place by shifting the buffer. */
1959         assert(VALID_WRITE_BUFFER(self));
1960         memmove(self->buffer, self->buffer + self->write_pos,
1961                 Py_SAFE_DOWNCAST(self->write_end - self->write_pos,
1962                                  Py_off_t, Py_ssize_t));
1963         self->write_end -= self->write_pos;
1964         self->raw_pos -= self->write_pos;
1965         self->pos -= self->write_pos;
1966         self->write_pos = 0;
1967         avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end,
1968                                  Py_off_t, Py_ssize_t);
1969         if (buffer->len <= avail) {
1970             /* Everything can be buffered */
1971             PyErr_Clear();
1972             memcpy(self->buffer + self->write_end, buffer->buf, buffer->len);
1973             self->write_end += buffer->len;
1974             self->pos += buffer->len;
1975             written = buffer->len;
1976             goto end;
1977         }
1978         /* Buffer as much as possible. */
1979         memcpy(self->buffer + self->write_end, buffer->buf, avail);
1980         self->write_end += avail;
1981         self->pos += avail;
1982         /* XXX Modifying the existing exception e using the pointer w
1983            will change e.characters_written but not e.args[2].
1984            Therefore we just replace with a new error. */
1985         _set_BlockingIOError("write could not complete without blocking",
1986                              avail);
1987         goto error;
1988     }
1989     Py_CLEAR(res);
1990 
1991     /* Adjust the raw stream position if it is away from the logical stream
1992        position. This happens if the read buffer has been filled but not
1993        modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind
1994        the raw stream by itself).
1995        Fixes issue #6629.
1996     */
1997     offset = RAW_OFFSET(self);
1998     if (offset != 0) {
1999         if (_buffered_raw_seek(self, -offset, 1) < 0)
2000             goto error;
2001         self->raw_pos -= offset;
2002     }
2003 
2004     /* Then write buf itself. At this point the buffer has been emptied. */
2005     remaining = buffer->len;
2006     written = 0;
2007     while (remaining > self->buffer_size) {
2008         Py_ssize_t n = _bufferedwriter_raw_write(
2009             self, (char *) buffer->buf + written, buffer->len - written);
2010         if (n == -1) {
2011             goto error;
2012         } else if (n == -2) {
2013             /* Write failed because raw file is non-blocking */
2014             if (remaining > self->buffer_size) {
2015                 /* Can't buffer everything, still buffer as much as possible */
2016                 memcpy(self->buffer,
2017                        (char *) buffer->buf + written, self->buffer_size);
2018                 self->raw_pos = 0;
2019                 ADJUST_POSITION(self, self->buffer_size);
2020                 self->write_end = self->buffer_size;
2021                 written += self->buffer_size;
2022                 _set_BlockingIOError("write could not complete without "
2023                                      "blocking", written);
2024                 goto error;
2025             }
2026             PyErr_Clear();
2027             break;
2028         }
2029         written += n;
2030         remaining -= n;
2031         /* Partial writes can return successfully when interrupted by a
2032            signal (see write(2)).  We must run signal handlers before
2033            blocking another time, possibly indefinitely. */
2034         if (PyErr_CheckSignals() < 0)
2035             goto error;
2036     }
2037     if (self->readable)
2038         _bufferedreader_reset_buf(self);
2039     if (remaining > 0) {
2040         memcpy(self->buffer, (char *) buffer->buf + written, remaining);
2041         written += remaining;
2042     }
2043     self->write_pos = 0;
2044     /* TODO: sanity check (remaining >= 0) */
2045     self->write_end = remaining;
2046     ADJUST_POSITION(self, remaining);
2047     self->raw_pos = 0;
2048 
2049 end:
2050     res = PyLong_FromSsize_t(written);
2051 
2052 error:
2053     LEAVE_BUFFERED(self)
2054     return res;
2055 }
2056 
2057 
2058 
2059 /*
2060  * BufferedRWPair
2061  */
2062 
2063 /* XXX The usefulness of this (compared to having two separate IO objects) is
2064  * questionable.
2065  */
2066 
2067 typedef struct {
2068     PyObject_HEAD
2069     buffered *reader;
2070     buffered *writer;
2071     PyObject *dict;
2072     PyObject *weakreflist;
2073 } rwpair;
2074 
2075 /*[clinic input]
2076 _io.BufferedRWPair.__init__
2077     reader: object
2078     writer: object
2079     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2080     /
2081 
2082 A buffered reader and writer object together.
2083 
2084 A buffered reader object and buffered writer object put together to
2085 form a sequential IO object that can read and write. This is typically
2086 used with a socket or two-way pipe.
2087 
2088 reader and writer are RawIOBase objects that are readable and
2089 writeable respectively. If the buffer_size is omitted it defaults to
2090 DEFAULT_BUFFER_SIZE.
2091 [clinic start generated code]*/
2092 
2093 static int
_io_BufferedRWPair___init___impl(rwpair * self,PyObject * reader,PyObject * writer,Py_ssize_t buffer_size)2094 _io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader,
2095                                  PyObject *writer, Py_ssize_t buffer_size)
2096 /*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/
2097 {
2098     if (_PyIOBase_check_readable(reader, Py_True) == NULL)
2099         return -1;
2100     if (_PyIOBase_check_writable(writer, Py_True) == NULL)
2101         return -1;
2102 
2103     self->reader = (buffered *) PyObject_CallFunction(
2104             (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size);
2105     if (self->reader == NULL)
2106         return -1;
2107 
2108     self->writer = (buffered *) PyObject_CallFunction(
2109             (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size);
2110     if (self->writer == NULL) {
2111         Py_CLEAR(self->reader);
2112         return -1;
2113     }
2114 
2115     return 0;
2116 }
2117 
2118 static int
bufferedrwpair_traverse(rwpair * self,visitproc visit,void * arg)2119 bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg)
2120 {
2121     Py_VISIT(self->dict);
2122     return 0;
2123 }
2124 
2125 static int
bufferedrwpair_clear(rwpair * self)2126 bufferedrwpair_clear(rwpair *self)
2127 {
2128     Py_CLEAR(self->reader);
2129     Py_CLEAR(self->writer);
2130     Py_CLEAR(self->dict);
2131     return 0;
2132 }
2133 
2134 static void
bufferedrwpair_dealloc(rwpair * self)2135 bufferedrwpair_dealloc(rwpair *self)
2136 {
2137     _PyObject_GC_UNTRACK(self);
2138     if (self->weakreflist != NULL)
2139         PyObject_ClearWeakRefs((PyObject *)self);
2140     Py_CLEAR(self->reader);
2141     Py_CLEAR(self->writer);
2142     Py_CLEAR(self->dict);
2143     Py_TYPE(self)->tp_free((PyObject *) self);
2144 }
2145 
2146 static PyObject *
_forward_call(buffered * self,_Py_Identifier * name,PyObject * args)2147 _forward_call(buffered *self, _Py_Identifier *name, PyObject *args)
2148 {
2149     PyObject *func, *ret;
2150     if (self == NULL) {
2151         PyErr_SetString(PyExc_ValueError,
2152                         "I/O operation on uninitialized object");
2153         return NULL;
2154     }
2155 
2156     func = _PyObject_GetAttrId((PyObject *)self, name);
2157     if (func == NULL) {
2158         PyErr_SetString(PyExc_AttributeError, name->string);
2159         return NULL;
2160     }
2161 
2162     ret = PyObject_CallObject(func, args);
2163     Py_DECREF(func);
2164     return ret;
2165 }
2166 
2167 static PyObject *
bufferedrwpair_read(rwpair * self,PyObject * args)2168 bufferedrwpair_read(rwpair *self, PyObject *args)
2169 {
2170     return _forward_call(self->reader, &PyId_read, args);
2171 }
2172 
2173 static PyObject *
bufferedrwpair_peek(rwpair * self,PyObject * args)2174 bufferedrwpair_peek(rwpair *self, PyObject *args)
2175 {
2176     return _forward_call(self->reader, &PyId_peek, args);
2177 }
2178 
2179 static PyObject *
bufferedrwpair_read1(rwpair * self,PyObject * args)2180 bufferedrwpair_read1(rwpair *self, PyObject *args)
2181 {
2182     return _forward_call(self->reader, &PyId_read1, args);
2183 }
2184 
2185 static PyObject *
bufferedrwpair_readinto(rwpair * self,PyObject * args)2186 bufferedrwpair_readinto(rwpair *self, PyObject *args)
2187 {
2188     return _forward_call(self->reader, &PyId_readinto, args);
2189 }
2190 
2191 static PyObject *
bufferedrwpair_readinto1(rwpair * self,PyObject * args)2192 bufferedrwpair_readinto1(rwpair *self, PyObject *args)
2193 {
2194     return _forward_call(self->reader, &PyId_readinto1, args);
2195 }
2196 
2197 static PyObject *
bufferedrwpair_write(rwpair * self,PyObject * args)2198 bufferedrwpair_write(rwpair *self, PyObject *args)
2199 {
2200     return _forward_call(self->writer, &PyId_write, args);
2201 }
2202 
2203 static PyObject *
bufferedrwpair_flush(rwpair * self,PyObject * Py_UNUSED (ignored))2204 bufferedrwpair_flush(rwpair *self, PyObject *Py_UNUSED(ignored))
2205 {
2206     return _forward_call(self->writer, &PyId_flush, NULL);
2207 }
2208 
2209 static PyObject *
bufferedrwpair_readable(rwpair * self,PyObject * Py_UNUSED (ignored))2210 bufferedrwpair_readable(rwpair *self, PyObject *Py_UNUSED(ignored))
2211 {
2212     return _forward_call(self->reader, &PyId_readable, NULL);
2213 }
2214 
2215 static PyObject *
bufferedrwpair_writable(rwpair * self,PyObject * Py_UNUSED (ignored))2216 bufferedrwpair_writable(rwpair *self, PyObject *Py_UNUSED(ignored))
2217 {
2218     return _forward_call(self->writer, &PyId_writable, NULL);
2219 }
2220 
2221 static PyObject *
bufferedrwpair_close(rwpair * self,PyObject * Py_UNUSED (ignored))2222 bufferedrwpair_close(rwpair *self, PyObject *Py_UNUSED(ignored))
2223 {
2224     PyObject *exc = NULL, *val, *tb;
2225     PyObject *ret = _forward_call(self->writer, &PyId_close, NULL);
2226     if (ret == NULL)
2227         PyErr_Fetch(&exc, &val, &tb);
2228     else
2229         Py_DECREF(ret);
2230     ret = _forward_call(self->reader, &PyId_close, NULL);
2231     if (exc != NULL) {
2232         _PyErr_ChainExceptions(exc, val, tb);
2233         Py_CLEAR(ret);
2234     }
2235     return ret;
2236 }
2237 
2238 static PyObject *
bufferedrwpair_isatty(rwpair * self,PyObject * Py_UNUSED (ignored))2239 bufferedrwpair_isatty(rwpair *self, PyObject *Py_UNUSED(ignored))
2240 {
2241     PyObject *ret = _forward_call(self->writer, &PyId_isatty, NULL);
2242 
2243     if (ret != Py_False) {
2244         /* either True or exception */
2245         return ret;
2246     }
2247     Py_DECREF(ret);
2248 
2249     return _forward_call(self->reader, &PyId_isatty, NULL);
2250 }
2251 
2252 static PyObject *
bufferedrwpair_closed_get(rwpair * self,void * context)2253 bufferedrwpair_closed_get(rwpair *self, void *context)
2254 {
2255     if (self->writer == NULL) {
2256         PyErr_SetString(PyExc_RuntimeError,
2257                 "the BufferedRWPair object is being garbage-collected");
2258         return NULL;
2259     }
2260     return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed);
2261 }
2262 
2263 
2264 
2265 /*
2266  * BufferedRandom
2267  */
2268 
2269 /*[clinic input]
2270 _io.BufferedRandom.__init__
2271     raw: object
2272     buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE
2273 
2274 A buffered interface to random access streams.
2275 
2276 The constructor creates a reader and writer for a seekable stream,
2277 raw, given in the first argument. If the buffer_size is omitted it
2278 defaults to DEFAULT_BUFFER_SIZE.
2279 [clinic start generated code]*/
2280 
2281 static int
_io_BufferedRandom___init___impl(buffered * self,PyObject * raw,Py_ssize_t buffer_size)2282 _io_BufferedRandom___init___impl(buffered *self, PyObject *raw,
2283                                  Py_ssize_t buffer_size)
2284 /*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/
2285 {
2286     self->ok = 0;
2287     self->detached = 0;
2288 
2289     if (_PyIOBase_check_seekable(raw, Py_True) == NULL)
2290         return -1;
2291     if (_PyIOBase_check_readable(raw, Py_True) == NULL)
2292         return -1;
2293     if (_PyIOBase_check_writable(raw, Py_True) == NULL)
2294         return -1;
2295 
2296     Py_INCREF(raw);
2297     Py_XSETREF(self->raw, raw);
2298     self->buffer_size = buffer_size;
2299     self->readable = 1;
2300     self->writable = 1;
2301 
2302     if (_buffered_init(self) < 0)
2303         return -1;
2304     _bufferedreader_reset_buf(self);
2305     _bufferedwriter_reset_buf(self);
2306     self->pos = 0;
2307 
2308     self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type &&
2309                                 Py_TYPE(raw) == &PyFileIO_Type);
2310 
2311     self->ok = 1;
2312     return 0;
2313 }
2314 
2315 #include "clinic/bufferedio.c.h"
2316 
2317 
2318 static PyMethodDef bufferediobase_methods[] = {
2319     _IO__BUFFEREDIOBASE_DETACH_METHODDEF
2320     {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc},
2321     {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc},
2322     _IO__BUFFEREDIOBASE_READINTO_METHODDEF
2323     _IO__BUFFEREDIOBASE_READINTO1_METHODDEF
2324     {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc},
2325     {NULL, NULL}
2326 };
2327 
2328 PyTypeObject PyBufferedIOBase_Type = {
2329     PyVarObject_HEAD_INIT(NULL, 0)
2330     "_io._BufferedIOBase",      /*tp_name*/
2331     0,                          /*tp_basicsize*/
2332     0,                          /*tp_itemsize*/
2333     0,                          /*tp_dealloc*/
2334     0,                          /*tp_vectorcall_offset*/
2335     0,                          /*tp_getattr*/
2336     0,                          /*tp_setattr*/
2337     0,                          /*tp_as_async*/
2338     0,                          /*tp_repr*/
2339     0,                          /*tp_as_number*/
2340     0,                          /*tp_as_sequence*/
2341     0,                          /*tp_as_mapping*/
2342     0,                          /*tp_hash */
2343     0,                          /*tp_call*/
2344     0,                          /*tp_str*/
2345     0,                          /*tp_getattro*/
2346     0,                          /*tp_setattro*/
2347     0,                          /*tp_as_buffer*/
2348     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
2349     bufferediobase_doc,         /* tp_doc */
2350     0,                          /* tp_traverse */
2351     0,                          /* tp_clear */
2352     0,                          /* tp_richcompare */
2353     0,                          /* tp_weaklistoffset */
2354     0,                          /* tp_iter */
2355     0,                          /* tp_iternext */
2356     bufferediobase_methods,     /* tp_methods */
2357     0,                          /* tp_members */
2358     0,                          /* tp_getset */
2359     &PyIOBase_Type,             /* tp_base */
2360     0,                          /* tp_dict */
2361     0,                          /* tp_descr_get */
2362     0,                          /* tp_descr_set */
2363     0,                          /* tp_dictoffset */
2364     0,                          /* tp_init */
2365     0,                          /* tp_alloc */
2366     0,                          /* tp_new */
2367     0,                          /* tp_free */
2368     0,                          /* tp_is_gc */
2369     0,                          /* tp_bases */
2370     0,                          /* tp_mro */
2371     0,                          /* tp_cache */
2372     0,                          /* tp_subclasses */
2373     0,                          /* tp_weaklist */
2374     0,                          /* tp_del */
2375     0,                          /* tp_version_tag */
2376     0,                          /* tp_finalize */
2377 };
2378 
2379 
2380 static PyMethodDef bufferedreader_methods[] = {
2381     /* BufferedIOMixin methods */
2382     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2383     {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS},
2384     {"close", (PyCFunction)buffered_close, METH_NOARGS},
2385     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2386     {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2387     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2388     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2389     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2390 
2391     _IO__BUFFERED_READ_METHODDEF
2392     _IO__BUFFERED_PEEK_METHODDEF
2393     _IO__BUFFERED_READ1_METHODDEF
2394     _IO__BUFFERED_READINTO_METHODDEF
2395     _IO__BUFFERED_READINTO1_METHODDEF
2396     _IO__BUFFERED_READLINE_METHODDEF
2397     _IO__BUFFERED_SEEK_METHODDEF
2398     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2399     _IO__BUFFERED_TRUNCATE_METHODDEF
2400     {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2401     {NULL, NULL}
2402 };
2403 
2404 static PyMemberDef bufferedreader_members[] = {
2405     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2406     {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2407     {NULL}
2408 };
2409 
2410 static PyGetSetDef bufferedreader_getset[] = {
2411     {"closed", (getter)buffered_closed_get, NULL, NULL},
2412     {"name", (getter)buffered_name_get, NULL, NULL},
2413     {"mode", (getter)buffered_mode_get, NULL, NULL},
2414     {NULL}
2415 };
2416 
2417 
2418 PyTypeObject PyBufferedReader_Type = {
2419     PyVarObject_HEAD_INIT(NULL, 0)
2420     "_io.BufferedReader",       /*tp_name*/
2421     sizeof(buffered),           /*tp_basicsize*/
2422     0,                          /*tp_itemsize*/
2423     (destructor)buffered_dealloc,     /*tp_dealloc*/
2424     0,                          /*tp_vectorcall_offset*/
2425     0,                          /*tp_getattr*/
2426     0,                          /*tp_setattr*/
2427     0,                          /*tp_as_async*/
2428     (reprfunc)buffered_repr,    /*tp_repr*/
2429     0,                          /*tp_as_number*/
2430     0,                          /*tp_as_sequence*/
2431     0,                          /*tp_as_mapping*/
2432     0,                          /*tp_hash */
2433     0,                          /*tp_call*/
2434     0,                          /*tp_str*/
2435     0,                          /*tp_getattro*/
2436     0,                          /*tp_setattro*/
2437     0,                          /*tp_as_buffer*/
2438     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2439         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2440     _io_BufferedReader___init____doc__, /* tp_doc */
2441     (traverseproc)buffered_traverse, /* tp_traverse */
2442     (inquiry)buffered_clear,    /* tp_clear */
2443     0,                          /* tp_richcompare */
2444     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2445     0,                          /* tp_iter */
2446     (iternextfunc)buffered_iternext, /* tp_iternext */
2447     bufferedreader_methods,     /* tp_methods */
2448     bufferedreader_members,     /* tp_members */
2449     bufferedreader_getset,      /* tp_getset */
2450     0,                          /* tp_base */
2451     0,                          /* tp_dict */
2452     0,                          /* tp_descr_get */
2453     0,                          /* tp_descr_set */
2454     offsetof(buffered, dict), /* tp_dictoffset */
2455     _io_BufferedReader___init__, /* tp_init */
2456     0,                          /* tp_alloc */
2457     PyType_GenericNew,          /* tp_new */
2458     0,                          /* tp_free */
2459     0,                          /* tp_is_gc */
2460     0,                          /* tp_bases */
2461     0,                          /* tp_mro */
2462     0,                          /* tp_cache */
2463     0,                          /* tp_subclasses */
2464     0,                          /* tp_weaklist */
2465     0,                          /* tp_del */
2466     0,                          /* tp_version_tag */
2467     0,                          /* tp_finalize */
2468 };
2469 
2470 
2471 static PyMethodDef bufferedwriter_methods[] = {
2472     /* BufferedIOMixin methods */
2473     {"close", (PyCFunction)buffered_close, METH_NOARGS},
2474     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2475     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2476     {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2477     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2478     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2479     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2480 
2481     _IO_BUFFEREDWRITER_WRITE_METHODDEF
2482     _IO__BUFFERED_TRUNCATE_METHODDEF
2483     {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2484     _IO__BUFFERED_SEEK_METHODDEF
2485     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2486     {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2487     {NULL, NULL}
2488 };
2489 
2490 static PyMemberDef bufferedwriter_members[] = {
2491     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2492     {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2493     {NULL}
2494 };
2495 
2496 static PyGetSetDef bufferedwriter_getset[] = {
2497     {"closed", (getter)buffered_closed_get, NULL, NULL},
2498     {"name", (getter)buffered_name_get, NULL, NULL},
2499     {"mode", (getter)buffered_mode_get, NULL, NULL},
2500     {NULL}
2501 };
2502 
2503 
2504 PyTypeObject PyBufferedWriter_Type = {
2505     PyVarObject_HEAD_INIT(NULL, 0)
2506     "_io.BufferedWriter",       /*tp_name*/
2507     sizeof(buffered),           /*tp_basicsize*/
2508     0,                          /*tp_itemsize*/
2509     (destructor)buffered_dealloc,     /*tp_dealloc*/
2510     0,                          /*tp_vectorcall_offset*/
2511     0,                          /*tp_getattr*/
2512     0,                          /*tp_setattr*/
2513     0,                          /*tp_as_async*/
2514     (reprfunc)buffered_repr,    /*tp_repr*/
2515     0,                          /*tp_as_number*/
2516     0,                          /*tp_as_sequence*/
2517     0,                          /*tp_as_mapping*/
2518     0,                          /*tp_hash */
2519     0,                          /*tp_call*/
2520     0,                          /*tp_str*/
2521     0,                          /*tp_getattro*/
2522     0,                          /*tp_setattro*/
2523     0,                          /*tp_as_buffer*/
2524     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2525         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2526     _io_BufferedWriter___init____doc__, /* tp_doc */
2527     (traverseproc)buffered_traverse, /* tp_traverse */
2528     (inquiry)buffered_clear,    /* tp_clear */
2529     0,                          /* tp_richcompare */
2530     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2531     0,                          /* tp_iter */
2532     0,                          /* tp_iternext */
2533     bufferedwriter_methods,     /* tp_methods */
2534     bufferedwriter_members,     /* tp_members */
2535     bufferedwriter_getset,      /* tp_getset */
2536     0,                          /* tp_base */
2537     0,                          /* tp_dict */
2538     0,                          /* tp_descr_get */
2539     0,                          /* tp_descr_set */
2540     offsetof(buffered, dict),   /* tp_dictoffset */
2541     _io_BufferedWriter___init__, /* tp_init */
2542     0,                          /* tp_alloc */
2543     PyType_GenericNew,          /* tp_new */
2544     0,                          /* tp_free */
2545     0,                          /* tp_is_gc */
2546     0,                          /* tp_bases */
2547     0,                          /* tp_mro */
2548     0,                          /* tp_cache */
2549     0,                          /* tp_subclasses */
2550     0,                          /* tp_weaklist */
2551     0,                          /* tp_del */
2552     0,                          /* tp_version_tag */
2553     0,                          /* tp_finalize */
2554 };
2555 
2556 
2557 static PyMethodDef bufferedrwpair_methods[] = {
2558     {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS},
2559     {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS},
2560     {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS},
2561     {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS},
2562     {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS},
2563 
2564     {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS},
2565     {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS},
2566 
2567     {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS},
2568     {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS},
2569 
2570     {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS},
2571     {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS},
2572 
2573     {NULL, NULL}
2574 };
2575 
2576 static PyGetSetDef bufferedrwpair_getset[] = {
2577     {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL},
2578     {NULL}
2579 };
2580 
2581 PyTypeObject PyBufferedRWPair_Type = {
2582     PyVarObject_HEAD_INIT(NULL, 0)
2583     "_io.BufferedRWPair",       /*tp_name*/
2584     sizeof(rwpair),            /*tp_basicsize*/
2585     0,                          /*tp_itemsize*/
2586     (destructor)bufferedrwpair_dealloc,     /*tp_dealloc*/
2587     0,                          /*tp_vectorcall_offset*/
2588     0,                          /*tp_getattr*/
2589     0,                          /*tp_setattr*/
2590     0,                          /*tp_as_async*/
2591     0,                          /*tp_repr*/
2592     0,                          /*tp_as_number*/
2593     0,                          /*tp_as_sequence*/
2594     0,                          /*tp_as_mapping*/
2595     0,                          /*tp_hash */
2596     0,                          /*tp_call*/
2597     0,                          /*tp_str*/
2598     0,                          /*tp_getattro*/
2599     0,                          /*tp_setattro*/
2600     0,                          /*tp_as_buffer*/
2601     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2602         | Py_TPFLAGS_HAVE_GC,   /* tp_flags */
2603     _io_BufferedRWPair___init____doc__, /* tp_doc */
2604     (traverseproc)bufferedrwpair_traverse, /* tp_traverse */
2605     (inquiry)bufferedrwpair_clear, /* tp_clear */
2606     0,                          /* tp_richcompare */
2607     offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/
2608     0,                          /* tp_iter */
2609     0,                          /* tp_iternext */
2610     bufferedrwpair_methods,     /* tp_methods */
2611     0,                          /* tp_members */
2612     bufferedrwpair_getset,      /* tp_getset */
2613     0,                          /* tp_base */
2614     0,                          /* tp_dict */
2615     0,                          /* tp_descr_get */
2616     0,                          /* tp_descr_set */
2617     offsetof(rwpair, dict),     /* tp_dictoffset */
2618     _io_BufferedRWPair___init__, /* tp_init */
2619     0,                          /* tp_alloc */
2620     PyType_GenericNew,          /* tp_new */
2621     0,                          /* tp_free */
2622     0,                          /* tp_is_gc */
2623     0,                          /* tp_bases */
2624     0,                          /* tp_mro */
2625     0,                          /* tp_cache */
2626     0,                          /* tp_subclasses */
2627     0,                          /* tp_weaklist */
2628     0,                          /* tp_del */
2629     0,                          /* tp_version_tag */
2630     0,                          /* tp_finalize */
2631 };
2632 
2633 
2634 static PyMethodDef bufferedrandom_methods[] = {
2635     /* BufferedIOMixin methods */
2636     {"close", (PyCFunction)buffered_close, METH_NOARGS},
2637     {"detach", (PyCFunction)buffered_detach, METH_NOARGS},
2638     {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
2639     {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
2640     {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
2641     {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
2642     {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
2643     {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
2644 
2645     {"flush", (PyCFunction)buffered_flush, METH_NOARGS},
2646 
2647     _IO__BUFFERED_SEEK_METHODDEF
2648     {"tell", (PyCFunction)buffered_tell, METH_NOARGS},
2649     _IO__BUFFERED_TRUNCATE_METHODDEF
2650     _IO__BUFFERED_READ_METHODDEF
2651     _IO__BUFFERED_READ1_METHODDEF
2652     _IO__BUFFERED_READINTO_METHODDEF
2653     _IO__BUFFERED_READINTO1_METHODDEF
2654     _IO__BUFFERED_READLINE_METHODDEF
2655     _IO__BUFFERED_PEEK_METHODDEF
2656     _IO_BUFFEREDWRITER_WRITE_METHODDEF
2657     {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS},
2658     {NULL, NULL}
2659 };
2660 
2661 static PyMemberDef bufferedrandom_members[] = {
2662     {"raw", T_OBJECT, offsetof(buffered, raw), READONLY},
2663     {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0},
2664     {NULL}
2665 };
2666 
2667 static PyGetSetDef bufferedrandom_getset[] = {
2668     {"closed", (getter)buffered_closed_get, NULL, NULL},
2669     {"name", (getter)buffered_name_get, NULL, NULL},
2670     {"mode", (getter)buffered_mode_get, NULL, NULL},
2671     {NULL}
2672 };
2673 
2674 
2675 PyTypeObject PyBufferedRandom_Type = {
2676     PyVarObject_HEAD_INIT(NULL, 0)
2677     "_io.BufferedRandom",       /*tp_name*/
2678     sizeof(buffered),           /*tp_basicsize*/
2679     0,                          /*tp_itemsize*/
2680     (destructor)buffered_dealloc,     /*tp_dealloc*/
2681     0,                          /*tp_vectorcall_offset*/
2682     0,                          /*tp_getattr*/
2683     0,                          /*tp_setattr*/
2684     0,                          /*tp_as_async*/
2685     (reprfunc)buffered_repr,    /*tp_repr*/
2686     0,                          /*tp_as_number*/
2687     0,                          /*tp_as_sequence*/
2688     0,                          /*tp_as_mapping*/
2689     0,                          /*tp_hash */
2690     0,                          /*tp_call*/
2691     0,                          /*tp_str*/
2692     0,                          /*tp_getattro*/
2693     0,                          /*tp_setattro*/
2694     0,                          /*tp_as_buffer*/
2695     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2696         | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
2697     _io_BufferedRandom___init____doc__, /* tp_doc */
2698     (traverseproc)buffered_traverse, /* tp_traverse */
2699     (inquiry)buffered_clear,    /* tp_clear */
2700     0,                          /* tp_richcompare */
2701     offsetof(buffered, weakreflist), /*tp_weaklistoffset*/
2702     0,                          /* tp_iter */
2703     (iternextfunc)buffered_iternext, /* tp_iternext */
2704     bufferedrandom_methods,     /* tp_methods */
2705     bufferedrandom_members,     /* tp_members */
2706     bufferedrandom_getset,      /* tp_getset */
2707     0,                          /* tp_base */
2708     0,                          /*tp_dict*/
2709     0,                          /* tp_descr_get */
2710     0,                          /* tp_descr_set */
2711     offsetof(buffered, dict), /*tp_dictoffset*/
2712     _io_BufferedRandom___init__, /* tp_init */
2713     0,                          /* tp_alloc */
2714     PyType_GenericNew,          /* tp_new */
2715     0,                          /* tp_free */
2716     0,                          /* tp_is_gc */
2717     0,                          /* tp_bases */
2718     0,                          /* tp_mro */
2719     0,                          /* tp_cache */
2720     0,                          /* tp_subclasses */
2721     0,                          /* tp_weaklist */
2722     0,                          /* tp_del */
2723     0,                          /* tp_version_tag */
2724     0,                          /* tp_finalize */
2725 };
2726