Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/Modules/_io/bytesio.c
Line
Count
Source (jump to first uncovered line)
1
#include "Python.h"
2
#include "pycore_object.h"
3
#include "structmember.h"       /* for offsetof() */
4
#include "_iomodule.h"
5
6
/*[clinic input]
7
module _io
8
class _io.BytesIO "bytesio *" "&PyBytesIO_Type"
9
[clinic start generated code]*/
10
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7f50ec034f5c0b26]*/
11
12
typedef struct {
13
    PyObject_HEAD
14
    PyObject *buf;
15
    Py_ssize_t pos;
16
    Py_ssize_t string_size;
17
    PyObject *dict;
18
    PyObject *weakreflist;
19
    Py_ssize_t exports;
20
} bytesio;
21
22
typedef struct {
23
    PyObject_HEAD
24
    bytesio *source;
25
} bytesiobuf;
26
27
/* The bytesio object can be in three states:
28
  * Py_REFCNT(buf) == 1, exports == 0.
29
  * Py_REFCNT(buf) > 1.  exports == 0,
30
    first modification or export causes the internal buffer copying.
31
  * exports > 0.  Py_REFCNT(buf) == 1, any modifications are forbidden.
32
*/
33
34
#define CHECK_CLOSED(self)                                  \
35
0
    if ((self)->buf == NULL) {                              \
36
0
        PyErr_SetString(PyExc_ValueError,                   \
37
0
                        "I/O operation on closed file.");   \
38
0
        return NULL;                                        \
39
0
    }
40
41
#define CHECK_EXPORTS(self) \
42
0
    if ((self)->exports > 0) { \
43
0
        PyErr_SetString(PyExc_BufferError, \
44
0
                        "Existing exports of data: object cannot be re-sized"); \
45
0
        return NULL; \
46
0
    }
47
48
0
#define SHARED_BUF(self) (Py_REFCNT((self)->buf) > 1)
49
50
51
/* Internal routine to get a line from the buffer of a BytesIO
52
   object. Returns the length between the current position to the
53
   next newline character. */
54
static Py_ssize_t
55
scan_eol(bytesio *self, Py_ssize_t len)
56
0
{
57
0
    const char *start, *n;
58
0
    Py_ssize_t maxlen;
59
60
0
    assert(self->buf != NULL);
61
0
    assert(self->pos >= 0);
62
63
0
    if (self->pos >= self->string_size)
64
0
        return 0;
65
66
    /* Move to the end of the line, up to the end of the string, s. */
67
0
    maxlen = self->string_size - self->pos;
68
0
    if (len < 0 || len > maxlen)
69
0
        len = maxlen;
70
71
0
    if (len) {
72
0
        start = PyBytes_AS_STRING(self->buf) + self->pos;
73
0
        n = memchr(start, '\n', len);
74
0
        if (n)
75
            /* Get the length from the current position to the end of
76
               the line. */
77
0
            len = n - start + 1;
78
0
    }
79
0
    assert(len >= 0);
80
0
    assert(self->pos < PY_SSIZE_T_MAX - len);
81
82
0
    return len;
83
0
}
84
85
/* Internal routine for detaching the shared buffer of BytesIO objects.
86
   The caller should ensure that the 'size' argument is non-negative and
87
   not lesser than self->string_size.  Returns 0 on success, -1 otherwise. */
88
static int
89
unshare_buffer(bytesio *self, size_t size)
90
0
{
91
0
    PyObject *new_buf;
92
0
    assert(SHARED_BUF(self));
93
0
    assert(self->exports == 0);
94
0
    assert(size >= (size_t)self->string_size);
95
0
    new_buf = PyBytes_FromStringAndSize(NULL, size);
96
0
    if (new_buf == NULL)
97
0
        return -1;
98
0
    memcpy(PyBytes_AS_STRING(new_buf), PyBytes_AS_STRING(self->buf),
99
0
           self->string_size);
100
0
    Py_SETREF(self->buf, new_buf);
101
0
    return 0;
102
0
}
103
104
/* Internal routine for changing the size of the buffer of BytesIO objects.
105
   The caller should ensure that the 'size' argument is non-negative.  Returns
106
   0 on success, -1 otherwise. */
107
static int
108
resize_buffer(bytesio *self, size_t size)
109
0
{
110
    /* Here, unsigned types are used to avoid dealing with signed integer
111
       overflow, which is undefined in C. */
112
0
    size_t alloc = PyBytes_GET_SIZE(self->buf);
113
114
0
    assert(self->buf != NULL);
115
116
    /* For simplicity, stay in the range of the signed type. Anyway, Python
117
       doesn't allow strings to be longer than this. */
118
0
    if (size > PY_SSIZE_T_MAX)
119
0
        goto overflow;
120
121
0
    if (size < alloc / 2) {
122
        /* Major downsize; resize down to exact size. */
123
0
        alloc = size + 1;
124
0
    }
125
0
    else if (size < alloc) {
126
        /* Within allocated size; quick exit */
127
0
        return 0;
128
0
    }
129
0
    else if (size <= alloc * 1.125) {
130
        /* Moderate upsize; overallocate similar to list_resize() */
131
0
        alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
132
0
    }
133
0
    else {
134
        /* Major upsize; resize up to exact size */
135
0
        alloc = size + 1;
136
0
    }
137
138
0
    if (alloc > ((size_t)-1) / sizeof(char))
139
0
        goto overflow;
140
141
0
    if (SHARED_BUF(self)) {
142
0
        if (unshare_buffer(self, alloc) < 0)
143
0
            return -1;
144
0
    }
145
0
    else {
146
0
        if (_PyBytes_Resize(&self->buf, alloc) < 0)
147
0
            return -1;
148
0
    }
149
150
0
    return 0;
151
152
0
  overflow:
153
0
    PyErr_SetString(PyExc_OverflowError,
154
0
                    "new buffer size too large");
155
0
    return -1;
156
0
}
157
158
/* Internal routine for writing a string of bytes to the buffer of a BytesIO
159
   object. Returns the number of bytes written, or -1 on error. */
160
static Py_ssize_t
161
write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
162
0
{
163
0
    size_t endpos;
164
0
    assert(self->buf != NULL);
165
0
    assert(self->pos >= 0);
166
0
    assert(len >= 0);
167
168
0
    endpos = (size_t)self->pos + len;
169
0
    if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) {
170
0
        if (resize_buffer(self, endpos) < 0)
171
0
            return -1;
172
0
    }
173
0
    else if (SHARED_BUF(self)) {
174
0
        if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0)
175
0
            return -1;
176
0
    }
177
178
0
    if (self->pos > self->string_size) {
179
        /* In case of overseek, pad with null bytes the buffer region between
180
           the end of stream and the current position.
181
182
          0   lo      string_size                           hi
183
          |   |<---used--->|<----------available----------->|
184
          |   |            <--to pad-->|<---to write--->    |
185
          0   buf                   position
186
        */
187
0
        memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0',
188
0
               (self->pos - self->string_size) * sizeof(char));
189
0
    }
190
191
    /* Copy the data to the internal buffer, overwriting some of the existing
192
       data if self->pos < self->string_size. */
193
0
    memcpy(PyBytes_AS_STRING(self->buf) + self->pos, bytes, len);
194
0
    self->pos = endpos;
195
196
    /* Set the new length of the internal string if it has changed. */
197
0
    if ((size_t)self->string_size < endpos) {
198
0
        self->string_size = endpos;
199
0
    }
200
201
0
    return len;
202
0
}
203
204
static PyObject *
205
bytesio_get_closed(bytesio *self, void *Py_UNUSED(ignored))
206
0
{
207
0
    if (self->buf == NULL) {
208
0
        Py_RETURN_TRUE;
209
0
    }
210
0
    else {
211
0
        Py_RETURN_FALSE;
212
0
    }
213
0
}
214
215
/*[clinic input]
216
_io.BytesIO.readable
217
218
Returns True if the IO object can be read.
219
[clinic start generated code]*/
220
221
static PyObject *
222
_io_BytesIO_readable_impl(bytesio *self)
223
/*[clinic end generated code: output=4e93822ad5b62263 input=96c5d0cccfb29f5c]*/
224
0
{
225
0
    CHECK_CLOSED(self);
226
0
    Py_RETURN_TRUE;
227
0
}
228
229
/*[clinic input]
230
_io.BytesIO.writable
231
232
Returns True if the IO object can be written.
233
[clinic start generated code]*/
234
235
static PyObject *
236
_io_BytesIO_writable_impl(bytesio *self)
237
/*[clinic end generated code: output=64ff6a254b1150b8 input=700eed808277560a]*/
238
0
{
239
0
    CHECK_CLOSED(self);
240
0
    Py_RETURN_TRUE;
241
0
}
242
243
/*[clinic input]
244
_io.BytesIO.seekable
245
246
Returns True if the IO object can be seeked.
247
[clinic start generated code]*/
248
249
static PyObject *
250
_io_BytesIO_seekable_impl(bytesio *self)
251
/*[clinic end generated code: output=6b417f46dcc09b56 input=9421f65627a344dd]*/
252
0
{
253
0
    CHECK_CLOSED(self);
254
0
    Py_RETURN_TRUE;
255
0
}
256
257
/*[clinic input]
258
_io.BytesIO.flush
259
260
Does nothing.
261
[clinic start generated code]*/
262
263
static PyObject *
264
_io_BytesIO_flush_impl(bytesio *self)
265
/*[clinic end generated code: output=187e3d781ca134a0 input=561ea490be4581a7]*/
266
0
{
267
0
    CHECK_CLOSED(self);
268
0
    Py_RETURN_NONE;
269
0
}
270
271
/*[clinic input]
272
_io.BytesIO.getbuffer
273
274
Get a read-write view over the contents of the BytesIO object.
275
[clinic start generated code]*/
276
277
static PyObject *
278
_io_BytesIO_getbuffer_impl(bytesio *self)
279
/*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/
280
0
{
281
0
    PyTypeObject *type = &_PyBytesIOBuffer_Type;
282
0
    bytesiobuf *buf;
283
0
    PyObject *view;
284
285
0
    CHECK_CLOSED(self);
286
287
0
    buf = (bytesiobuf *) type->tp_alloc(type, 0);
288
0
    if (buf == NULL)
289
0
        return NULL;
290
0
    Py_INCREF(self);
291
0
    buf->source = self;
292
0
    view = PyMemoryView_FromObject((PyObject *) buf);
293
0
    Py_DECREF(buf);
294
0
    return view;
295
0
}
296
297
/*[clinic input]
298
_io.BytesIO.getvalue
299
300
Retrieve the entire contents of the BytesIO object.
301
[clinic start generated code]*/
302
303
static PyObject *
304
_io_BytesIO_getvalue_impl(bytesio *self)
305
/*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/
306
0
{
307
0
    CHECK_CLOSED(self);
308
0
    if (self->string_size <= 1 || self->exports > 0)
309
0
        return PyBytes_FromStringAndSize(PyBytes_AS_STRING(self->buf),
310
0
                                         self->string_size);
311
312
0
    if (self->string_size != PyBytes_GET_SIZE(self->buf)) {
313
0
        if (SHARED_BUF(self)) {
314
0
            if (unshare_buffer(self, self->string_size) < 0)
315
0
                return NULL;
316
0
        }
317
0
        else {
318
0
            if (_PyBytes_Resize(&self->buf, self->string_size) < 0)
319
0
                return NULL;
320
0
        }
321
0
    }
322
0
    Py_INCREF(self->buf);
323
0
    return self->buf;
324
0
}
325
326
/*[clinic input]
327
_io.BytesIO.isatty
328
329
Always returns False.
330
331
BytesIO objects are not connected to a TTY-like device.
332
[clinic start generated code]*/
333
334
static PyObject *
335
_io_BytesIO_isatty_impl(bytesio *self)
336
/*[clinic end generated code: output=df67712e669f6c8f input=6f97f0985d13f827]*/
337
0
{
338
0
    CHECK_CLOSED(self);
339
0
    Py_RETURN_FALSE;
340
0
}
341
342
/*[clinic input]
343
_io.BytesIO.tell
344
345
Current file position, an integer.
346
[clinic start generated code]*/
347
348
static PyObject *
349
_io_BytesIO_tell_impl(bytesio *self)
350
/*[clinic end generated code: output=b54b0f93cd0e5e1d input=b106adf099cb3657]*/
351
0
{
352
0
    CHECK_CLOSED(self);
353
0
    return PyLong_FromSsize_t(self->pos);
354
0
}
355
356
static PyObject *
357
read_bytes(bytesio *self, Py_ssize_t size)
358
0
{
359
0
    char *output;
360
361
0
    assert(self->buf != NULL);
362
0
    assert(size <= self->string_size);
363
0
    if (size > 1 &&
364
0
        self->pos == 0 && size == PyBytes_GET_SIZE(self->buf) &&
365
0
        self->exports == 0) {
366
0
        self->pos += size;
367
0
        Py_INCREF(self->buf);
368
0
        return self->buf;
369
0
    }
370
371
0
    output = PyBytes_AS_STRING(self->buf) + self->pos;
372
0
    self->pos += size;
373
0
    return PyBytes_FromStringAndSize(output, size);
374
0
}
375
376
/*[clinic input]
377
_io.BytesIO.read
378
    size: Py_ssize_t(accept={int, NoneType}) = -1
379
    /
380
381
Read at most size bytes, returned as a bytes object.
382
383
If the size argument is negative, read until EOF is reached.
384
Return an empty bytes object at EOF.
385
[clinic start generated code]*/
386
387
static PyObject *
388
_io_BytesIO_read_impl(bytesio *self, Py_ssize_t size)
389
/*[clinic end generated code: output=9cc025f21c75bdd2 input=74344a39f431c3d7]*/
390
0
{
391
0
    Py_ssize_t n;
392
393
0
    CHECK_CLOSED(self);
394
395
    /* adjust invalid sizes */
396
0
    n = self->string_size - self->pos;
397
0
    if (size < 0 || size > n) {
398
0
        size = n;
399
0
        if (size < 0)
400
0
            size = 0;
401
0
    }
402
403
0
    return read_bytes(self, size);
404
0
}
405
406
407
/*[clinic input]
408
_io.BytesIO.read1
409
    size: Py_ssize_t(accept={int, NoneType}) = -1
410
    /
411
412
Read at most size bytes, returned as a bytes object.
413
414
If the size argument is negative or omitted, read until EOF is reached.
415
Return an empty bytes object at EOF.
416
[clinic start generated code]*/
417
418
static PyObject *
419
_io_BytesIO_read1_impl(bytesio *self, Py_ssize_t size)
420
/*[clinic end generated code: output=d0f843285aa95f1c input=440a395bf9129ef5]*/
421
0
{
422
0
    return _io_BytesIO_read_impl(self, size);
423
0
}
424
425
/*[clinic input]
426
_io.BytesIO.readline
427
    size: Py_ssize_t(accept={int, NoneType}) = -1
428
    /
429
430
Next line from the file, as a bytes object.
431
432
Retain newline.  A non-negative size argument limits the maximum
433
number of bytes to return (an incomplete line may be returned then).
434
Return an empty bytes object at EOF.
435
[clinic start generated code]*/
436
437
static PyObject *
438
_io_BytesIO_readline_impl(bytesio *self, Py_ssize_t size)
439
/*[clinic end generated code: output=4bff3c251df8ffcd input=e7c3fbd1744e2783]*/
440
0
{
441
0
    Py_ssize_t n;
442
443
0
    CHECK_CLOSED(self);
444
445
0
    n = scan_eol(self, size);
446
447
0
    return read_bytes(self, n);
448
0
}
449
450
/*[clinic input]
451
_io.BytesIO.readlines
452
    size as arg: object = None
453
    /
454
455
List of bytes objects, each a line from the file.
456
457
Call readline() repeatedly and return a list of the lines so read.
458
The optional size argument, if given, is an approximate bound on the
459
total number of bytes in the lines returned.
460
[clinic start generated code]*/
461
462
static PyObject *
463
_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg)
464
/*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/
465
0
{
466
0
    Py_ssize_t maxsize, size, n;
467
0
    PyObject *result, *line;
468
0
    char *output;
469
470
0
    CHECK_CLOSED(self);
471
472
0
    if (PyLong_Check(arg)) {
473
0
        maxsize = PyLong_AsSsize_t(arg);
474
0
        if (maxsize == -1 && PyErr_Occurred())
475
0
            return NULL;
476
0
    }
477
0
    else if (arg == Py_None) {
478
        /* No size limit, by default. */
479
0
        maxsize = -1;
480
0
    }
481
0
    else {
482
0
        PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
483
0
                     Py_TYPE(arg)->tp_name);
484
0
        return NULL;
485
0
    }
486
487
0
    size = 0;
488
0
    result = PyList_New(0);
489
0
    if (!result)
490
0
        return NULL;
491
492
0
    output = PyBytes_AS_STRING(self->buf) + self->pos;
493
0
    while ((n = scan_eol(self, -1)) != 0) {
494
0
        self->pos += n;
495
0
        line = PyBytes_FromStringAndSize(output, n);
496
0
        if (!line)
497
0
            goto on_error;
498
0
        if (PyList_Append(result, line) == -1) {
499
0
            Py_DECREF(line);
500
0
            goto on_error;
501
0
        }
502
0
        Py_DECREF(line);
503
0
        size += n;
504
0
        if (maxsize > 0 && size >= maxsize)
505
0
            break;
506
0
        output += n;
507
0
    }
508
0
    return result;
509
510
0
  on_error:
511
0
    Py_DECREF(result);
512
0
    return NULL;
513
0
}
514
515
/*[clinic input]
516
_io.BytesIO.readinto
517
    buffer: Py_buffer(accept={rwbuffer})
518
    /
519
520
Read bytes into buffer.
521
522
Returns number of bytes read (0 for EOF), or None if the object
523
is set not to block and has no data to read.
524
[clinic start generated code]*/
525
526
static PyObject *
527
_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
528
/*[clinic end generated code: output=a5d407217dcf0639 input=1424d0fdce857919]*/
529
0
{
530
0
    Py_ssize_t len, n;
531
532
0
    CHECK_CLOSED(self);
533
534
    /* adjust invalid sizes */
535
0
    len = buffer->len;
536
0
    n = self->string_size - self->pos;
537
0
    if (len > n) {
538
0
        len = n;
539
0
        if (len < 0)
540
0
            len = 0;
541
0
    }
542
543
0
    memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
544
0
    assert(self->pos + len < PY_SSIZE_T_MAX);
545
0
    assert(len >= 0);
546
0
    self->pos += len;
547
548
0
    return PyLong_FromSsize_t(len);
549
0
}
550
551
/*[clinic input]
552
_io.BytesIO.truncate
553
    size: Py_ssize_t(accept={int, NoneType}, c_default="self->pos") = None
554
    /
555
556
Truncate the file to at most size bytes.
557
558
Size defaults to the current file position, as returned by tell().
559
The current file position is unchanged.  Returns the new size.
560
[clinic start generated code]*/
561
562
static PyObject *
563
_io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size)
564
/*[clinic end generated code: output=9ad17650c15fa09b input=423759dd42d2f7c1]*/
565
0
{
566
0
    CHECK_CLOSED(self);
567
0
    CHECK_EXPORTS(self);
568
569
0
    if (size < 0) {
570
0
        PyErr_Format(PyExc_ValueError,
571
0
                     "negative size value %zd", size);
572
0
        return NULL;
573
0
    }
574
575
0
    if (size < self->string_size) {
576
0
        self->string_size = size;
577
0
        if (resize_buffer(self, size) < 0)
578
0
            return NULL;
579
0
    }
580
581
0
    return PyLong_FromSsize_t(size);
582
0
}
583
584
static PyObject *
585
bytesio_iternext(bytesio *self)
586
0
{
587
0
    Py_ssize_t n;
588
589
0
    CHECK_CLOSED(self);
590
591
0
    n = scan_eol(self, -1);
592
593
0
    if (n == 0)
594
0
        return NULL;
595
596
0
    return read_bytes(self, n);
597
0
}
598
599
/*[clinic input]
600
_io.BytesIO.seek
601
    pos: Py_ssize_t
602
    whence: int = 0
603
    /
604
605
Change stream position.
606
607
Seek to byte offset pos relative to position indicated by whence:
608
     0  Start of stream (the default).  pos should be >= 0;
609
     1  Current position - pos may be negative;
610
     2  End of stream - pos usually negative.
611
Returns the new absolute position.
612
[clinic start generated code]*/
613
614
static PyObject *
615
_io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence)
616
/*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/
617
0
{
618
0
    CHECK_CLOSED(self);
619
620
0
    if (pos < 0 && whence == 0) {
621
0
        PyErr_Format(PyExc_ValueError,
622
0
                     "negative seek value %zd", pos);
623
0
        return NULL;
624
0
    }
625
626
    /* whence = 0: offset relative to beginning of the string.
627
       whence = 1: offset relative to current position.
628
       whence = 2: offset relative the end of the string. */
629
0
    if (whence == 1) {
630
0
        if (pos > PY_SSIZE_T_MAX - self->pos) {
631
0
            PyErr_SetString(PyExc_OverflowError,
632
0
                            "new position too large");
633
0
            return NULL;
634
0
        }
635
0
        pos += self->pos;
636
0
    }
637
0
    else if (whence == 2) {
638
0
        if (pos > PY_SSIZE_T_MAX - self->string_size) {
639
0
            PyErr_SetString(PyExc_OverflowError,
640
0
                            "new position too large");
641
0
            return NULL;
642
0
        }
643
0
        pos += self->string_size;
644
0
    }
645
0
    else if (whence != 0) {
646
0
        PyErr_Format(PyExc_ValueError,
647
0
                     "invalid whence (%i, should be 0, 1 or 2)", whence);
648
0
        return NULL;
649
0
    }
650
651
0
    if (pos < 0)
652
0
        pos = 0;
653
0
    self->pos = pos;
654
655
0
    return PyLong_FromSsize_t(self->pos);
656
0
}
657
658
/*[clinic input]
659
_io.BytesIO.write
660
    b: object
661
    /
662
663
Write bytes to file.
664
665
Return the number of bytes written.
666
[clinic start generated code]*/
667
668
static PyObject *
669
_io_BytesIO_write(bytesio *self, PyObject *b)
670
/*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/
671
0
{
672
0
    Py_ssize_t n = 0;
673
0
    Py_buffer buf;
674
675
0
    CHECK_CLOSED(self);
676
0
    CHECK_EXPORTS(self);
677
678
0
    if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0)
679
0
        return NULL;
680
681
0
    if (buf.len != 0)
682
0
        n = write_bytes(self, buf.buf, buf.len);
683
684
0
    PyBuffer_Release(&buf);
685
0
    return n >= 0 ? PyLong_FromSsize_t(n) : NULL;
686
0
}
687
688
/*[clinic input]
689
_io.BytesIO.writelines
690
    lines: object
691
    /
692
693
Write lines to the file.
694
695
Note that newlines are not added.  lines can be any iterable object
696
producing bytes-like objects. This is equivalent to calling write() for
697
each element.
698
[clinic start generated code]*/
699
700
static PyObject *
701
_io_BytesIO_writelines(bytesio *self, PyObject *lines)
702
/*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/
703
0
{
704
0
    PyObject *it, *item;
705
0
    PyObject *ret;
706
707
0
    CHECK_CLOSED(self);
708
709
0
    it = PyObject_GetIter(lines);
710
0
    if (it == NULL)
711
0
        return NULL;
712
713
0
    while ((item = PyIter_Next(it)) != NULL) {
714
0
        ret = _io_BytesIO_write(self, item);
715
0
        Py_DECREF(item);
716
0
        if (ret == NULL) {
717
0
            Py_DECREF(it);
718
0
            return NULL;
719
0
        }
720
0
        Py_DECREF(ret);
721
0
    }
722
0
    Py_DECREF(it);
723
724
    /* See if PyIter_Next failed */
725
0
    if (PyErr_Occurred())
726
0
        return NULL;
727
728
0
    Py_RETURN_NONE;
729
0
}
730
731
/*[clinic input]
732
_io.BytesIO.close
733
734
Disable all I/O operations.
735
[clinic start generated code]*/
736
737
static PyObject *
738
_io_BytesIO_close_impl(bytesio *self)
739
/*[clinic end generated code: output=1471bb9411af84a0 input=37e1f55556e61f60]*/
740
0
{
741
0
    CHECK_EXPORTS(self);
742
0
    Py_CLEAR(self->buf);
743
0
    Py_RETURN_NONE;
744
0
}
745
746
/* Pickling support.
747
748
   Note that only pickle protocol 2 and onward are supported since we use
749
   extended __reduce__ API of PEP 307 to make BytesIO instances picklable.
750
751
   Providing support for protocol < 2 would require the __reduce_ex__ method
752
   which is notably long-winded when defined properly.
753
754
   For BytesIO, the implementation would similar to one coded for
755
   object.__reduce_ex__, but slightly less general. To be more specific, we
756
   could call bytesio_getstate directly and avoid checking for the presence of
757
   a fallback __reduce__ method. However, we would still need a __newobj__
758
   function to use the efficient instance representation of PEP 307.
759
 */
760
761
static PyObject *
762
bytesio_getstate(bytesio *self, PyObject *Py_UNUSED(ignored))
763
0
{
764
0
    PyObject *initvalue = _io_BytesIO_getvalue_impl(self);
765
0
    PyObject *dict;
766
0
    PyObject *state;
767
768
0
    if (initvalue == NULL)
769
0
        return NULL;
770
0
    if (self->dict == NULL) {
771
0
        Py_INCREF(Py_None);
772
0
        dict = Py_None;
773
0
    }
774
0
    else {
775
0
        dict = PyDict_Copy(self->dict);
776
0
        if (dict == NULL) {
777
0
            Py_DECREF(initvalue);
778
0
            return NULL;
779
0
        }
780
0
    }
781
782
0
    state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
783
0
    Py_DECREF(initvalue);
784
0
    return state;
785
0
}
786
787
static PyObject *
788
bytesio_setstate(bytesio *self, PyObject *state)
789
0
{
790
0
    PyObject *result;
791
0
    PyObject *position_obj;
792
0
    PyObject *dict;
793
0
    Py_ssize_t pos;
794
795
0
    assert(state != NULL);
796
797
    /* We allow the state tuple to be longer than 3, because we may need
798
       someday to extend the object's state without breaking
799
       backward-compatibility. */
800
0
    if (!PyTuple_Check(state) || PyTuple_GET_SIZE(state) < 3) {
801
0
        PyErr_Format(PyExc_TypeError,
802
0
                     "%.200s.__setstate__ argument should be 3-tuple, got %.200s",
803
0
                     Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
804
0
        return NULL;
805
0
    }
806
0
    CHECK_EXPORTS(self);
807
    /* Reset the object to its default state. This is only needed to handle
808
       the case of repeated calls to __setstate__. */
809
0
    self->string_size = 0;
810
0
    self->pos = 0;
811
812
    /* Set the value of the internal buffer. If state[0] does not support the
813
       buffer protocol, bytesio_write will raise the appropriate TypeError. */
814
0
    result = _io_BytesIO_write(self, PyTuple_GET_ITEM(state, 0));
815
0
    if (result == NULL)
816
0
        return NULL;
817
0
    Py_DECREF(result);
818
819
    /* Set carefully the position value. Alternatively, we could use the seek
820
       method instead of modifying self->pos directly to better protect the
821
       object internal state against erroneous (or malicious) inputs. */
822
0
    position_obj = PyTuple_GET_ITEM(state, 1);
823
0
    if (!PyLong_Check(position_obj)) {
824
0
        PyErr_Format(PyExc_TypeError,
825
0
                     "second item of state must be an integer, not %.200s",
826
0
                     Py_TYPE(position_obj)->tp_name);
827
0
        return NULL;
828
0
    }
829
0
    pos = PyLong_AsSsize_t(position_obj);
830
0
    if (pos == -1 && PyErr_Occurred())
831
0
        return NULL;
832
0
    if (pos < 0) {
833
0
        PyErr_SetString(PyExc_ValueError,
834
0
                        "position value cannot be negative");
835
0
        return NULL;
836
0
    }
837
0
    self->pos = pos;
838
839
    /* Set the dictionary of the instance variables. */
840
0
    dict = PyTuple_GET_ITEM(state, 2);
841
0
    if (dict != Py_None) {
842
0
        if (!PyDict_Check(dict)) {
843
0
            PyErr_Format(PyExc_TypeError,
844
0
                         "third item of state should be a dict, got a %.200s",
845
0
                         Py_TYPE(dict)->tp_name);
846
0
            return NULL;
847
0
        }
848
0
        if (self->dict) {
849
            /* Alternatively, we could replace the internal dictionary
850
               completely. However, it seems more practical to just update it. */
851
0
            if (PyDict_Update(self->dict, dict) < 0)
852
0
                return NULL;
853
0
        }
854
0
        else {
855
0
            Py_INCREF(dict);
856
0
            self->dict = dict;
857
0
        }
858
0
    }
859
860
0
    Py_RETURN_NONE;
861
0
}
862
863
static void
864
bytesio_dealloc(bytesio *self)
865
0
{
866
0
    _PyObject_GC_UNTRACK(self);
867
0
    if (self->exports > 0) {
868
0
        PyErr_SetString(PyExc_SystemError,
869
0
                        "deallocated BytesIO object has exported buffers");
870
0
        PyErr_Print();
871
0
    }
872
0
    Py_CLEAR(self->buf);
873
0
    Py_CLEAR(self->dict);
874
0
    if (self->weakreflist != NULL)
875
0
        PyObject_ClearWeakRefs((PyObject *) self);
876
0
    Py_TYPE(self)->tp_free(self);
877
0
}
878
879
static PyObject *
880
bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
881
0
{
882
0
    bytesio *self;
883
884
0
    assert(type != NULL && type->tp_alloc != NULL);
885
0
    self = (bytesio *)type->tp_alloc(type, 0);
886
0
    if (self == NULL)
887
0
        return NULL;
888
889
    /* tp_alloc initializes all the fields to zero. So we don't have to
890
       initialize them here. */
891
892
0
    self->buf = PyBytes_FromStringAndSize(NULL, 0);
893
0
    if (self->buf == NULL) {
894
0
        Py_DECREF(self);
895
0
        return PyErr_NoMemory();
896
0
    }
897
898
0
    return (PyObject *)self;
899
0
}
900
901
/*[clinic input]
902
_io.BytesIO.__init__
903
    initial_bytes as initvalue: object(c_default="NULL") = b''
904
905
Buffered I/O implementation using an in-memory bytes buffer.
906
[clinic start generated code]*/
907
908
static int
909
_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
910
/*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/
911
0
{
912
    /* In case, __init__ is called multiple times. */
913
0
    self->string_size = 0;
914
0
    self->pos = 0;
915
916
0
    if (self->exports > 0) {
917
0
        PyErr_SetString(PyExc_BufferError,
918
0
                        "Existing exports of data: object cannot be re-sized");
919
0
        return -1;
920
0
    }
921
0
    if (initvalue && initvalue != Py_None) {
922
0
        if (PyBytes_CheckExact(initvalue)) {
923
0
            Py_INCREF(initvalue);
924
0
            Py_XSETREF(self->buf, initvalue);
925
0
            self->string_size = PyBytes_GET_SIZE(initvalue);
926
0
        }
927
0
        else {
928
0
            PyObject *res;
929
0
            res = _io_BytesIO_write(self, initvalue);
930
0
            if (res == NULL)
931
0
                return -1;
932
0
            Py_DECREF(res);
933
0
            self->pos = 0;
934
0
        }
935
0
    }
936
937
0
    return 0;
938
0
}
939
940
static PyObject *
941
bytesio_sizeof(bytesio *self, void *unused)
942
0
{
943
0
    Py_ssize_t res;
944
945
0
    res = _PyObject_SIZE(Py_TYPE(self));
946
0
    if (self->buf && !SHARED_BUF(self)) {
947
0
        Py_ssize_t s = _PySys_GetSizeOf(self->buf);
948
0
        if (s == -1) {
949
0
            return NULL;
950
0
        }
951
0
        res += s;
952
0
    }
953
0
    return PyLong_FromSsize_t(res);
954
0
}
955
956
static int
957
bytesio_traverse(bytesio *self, visitproc visit, void *arg)
958
0
{
959
0
    Py_VISIT(self->dict);
960
0
    return 0;
961
0
}
962
963
static int
964
bytesio_clear(bytesio *self)
965
0
{
966
0
    Py_CLEAR(self->dict);
967
0
    return 0;
968
0
}
969
970
971
#include "clinic/bytesio.c.h"
972
973
static PyGetSetDef bytesio_getsetlist[] = {
974
    {"closed",  (getter)bytesio_get_closed, NULL,
975
     "True if the file is closed."},
976
    {NULL},            /* sentinel */
977
};
978
979
static struct PyMethodDef bytesio_methods[] = {
980
    _IO_BYTESIO_READABLE_METHODDEF
981
    _IO_BYTESIO_SEEKABLE_METHODDEF
982
    _IO_BYTESIO_WRITABLE_METHODDEF
983
    _IO_BYTESIO_CLOSE_METHODDEF
984
    _IO_BYTESIO_FLUSH_METHODDEF
985
    _IO_BYTESIO_ISATTY_METHODDEF
986
    _IO_BYTESIO_TELL_METHODDEF
987
    _IO_BYTESIO_WRITE_METHODDEF
988
    _IO_BYTESIO_WRITELINES_METHODDEF
989
    _IO_BYTESIO_READ1_METHODDEF
990
    _IO_BYTESIO_READINTO_METHODDEF
991
    _IO_BYTESIO_READLINE_METHODDEF
992
    _IO_BYTESIO_READLINES_METHODDEF
993
    _IO_BYTESIO_READ_METHODDEF
994
    _IO_BYTESIO_GETBUFFER_METHODDEF
995
    _IO_BYTESIO_GETVALUE_METHODDEF
996
    _IO_BYTESIO_SEEK_METHODDEF
997
    _IO_BYTESIO_TRUNCATE_METHODDEF
998
    {"__getstate__",  (PyCFunction)bytesio_getstate,  METH_NOARGS, NULL},
999
    {"__setstate__",  (PyCFunction)bytesio_setstate,  METH_O, NULL},
1000
    {"__sizeof__", (PyCFunction)bytesio_sizeof,     METH_NOARGS, NULL},
1001
    {NULL, NULL}        /* sentinel */
1002
};
1003
1004
PyTypeObject PyBytesIO_Type = {
1005
    PyVarObject_HEAD_INIT(NULL, 0)
1006
    "_io.BytesIO",                             /*tp_name*/
1007
    sizeof(bytesio),                     /*tp_basicsize*/
1008
    0,                                         /*tp_itemsize*/
1009
    (destructor)bytesio_dealloc,               /*tp_dealloc*/
1010
    0,                                         /*tp_vectorcall_offset*/
1011
    0,                                         /*tp_getattr*/
1012
    0,                                         /*tp_setattr*/
1013
    0,                                         /*tp_as_async*/
1014
    0,                                         /*tp_repr*/
1015
    0,                                         /*tp_as_number*/
1016
    0,                                         /*tp_as_sequence*/
1017
    0,                                         /*tp_as_mapping*/
1018
    0,                                         /*tp_hash*/
1019
    0,                                         /*tp_call*/
1020
    0,                                         /*tp_str*/
1021
    0,                                         /*tp_getattro*/
1022
    0,                                         /*tp_setattro*/
1023
    0,                                         /*tp_as_buffer*/
1024
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1025
    Py_TPFLAGS_HAVE_GC,                        /*tp_flags*/
1026
    _io_BytesIO___init____doc__,               /*tp_doc*/
1027
    (traverseproc)bytesio_traverse,            /*tp_traverse*/
1028
    (inquiry)bytesio_clear,                    /*tp_clear*/
1029
    0,                                         /*tp_richcompare*/
1030
    offsetof(bytesio, weakreflist),      /*tp_weaklistoffset*/
1031
    PyObject_SelfIter,                         /*tp_iter*/
1032
    (iternextfunc)bytesio_iternext,            /*tp_iternext*/
1033
    bytesio_methods,                           /*tp_methods*/
1034
    0,                                         /*tp_members*/
1035
    bytesio_getsetlist,                        /*tp_getset*/
1036
    0,                                         /*tp_base*/
1037
    0,                                         /*tp_dict*/
1038
    0,                                         /*tp_descr_get*/
1039
    0,                                         /*tp_descr_set*/
1040
    offsetof(bytesio, dict),             /*tp_dictoffset*/
1041
    _io_BytesIO___init__,                      /*tp_init*/
1042
    0,                                         /*tp_alloc*/
1043
    bytesio_new,                               /*tp_new*/
1044
};
1045
1046
1047
/*
1048
 * Implementation of the small intermediate object used by getbuffer().
1049
 * getbuffer() returns a memoryview over this object, which should make it
1050
 * invisible from Python code.
1051
 */
1052
1053
static int
1054
bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
1055
0
{
1056
0
    bytesio *b = (bytesio *) obj->source;
1057
1058
0
    if (view == NULL) {
1059
0
        PyErr_SetString(PyExc_BufferError,
1060
0
            "bytesiobuf_getbuffer: view==NULL argument is obsolete");
1061
0
        return -1;
1062
0
    }
1063
0
    if (SHARED_BUF(b)) {
1064
0
        if (unshare_buffer(b, b->string_size) < 0)
1065
0
            return -1;
1066
0
    }
1067
1068
    /* cannot fail if view != NULL and readonly == 0 */
1069
0
    (void)PyBuffer_FillInfo(view, (PyObject*)obj,
1070
0
                            PyBytes_AS_STRING(b->buf), b->string_size,
1071
0
                            0, flags);
1072
0
    b->exports++;
1073
0
    return 0;
1074
0
}
1075
1076
static void
1077
bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view)
1078
0
{
1079
0
    bytesio *b = (bytesio *) obj->source;
1080
0
    b->exports--;
1081
0
}
1082
1083
static int
1084
bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg)
1085
0
{
1086
0
    Py_VISIT(self->source);
1087
0
    return 0;
1088
0
}
1089
1090
static void
1091
bytesiobuf_dealloc(bytesiobuf *self)
1092
0
{
1093
    /* bpo-31095: UnTrack is needed before calling any callbacks */
1094
0
    PyObject_GC_UnTrack(self);
1095
0
    Py_CLEAR(self->source);
1096
0
    Py_TYPE(self)->tp_free(self);
1097
0
}
1098
1099
static PyBufferProcs bytesiobuf_as_buffer = {
1100
    (getbufferproc) bytesiobuf_getbuffer,
1101
    (releasebufferproc) bytesiobuf_releasebuffer,
1102
};
1103
1104
PyTypeObject _PyBytesIOBuffer_Type = {
1105
    PyVarObject_HEAD_INIT(NULL, 0)
1106
    "_io._BytesIOBuffer",                      /*tp_name*/
1107
    sizeof(bytesiobuf),                        /*tp_basicsize*/
1108
    0,                                         /*tp_itemsize*/
1109
    (destructor)bytesiobuf_dealloc,            /*tp_dealloc*/
1110
    0,                                         /*tp_vectorcall_offset*/
1111
    0,                                         /*tp_getattr*/
1112
    0,                                         /*tp_setattr*/
1113
    0,                                         /*tp_as_async*/
1114
    0,                                         /*tp_repr*/
1115
    0,                                         /*tp_as_number*/
1116
    0,                                         /*tp_as_sequence*/
1117
    0,                                         /*tp_as_mapping*/
1118
    0,                                         /*tp_hash*/
1119
    0,                                         /*tp_call*/
1120
    0,                                         /*tp_str*/
1121
    0,                                         /*tp_getattro*/
1122
    0,                                         /*tp_setattro*/
1123
    &bytesiobuf_as_buffer,                     /*tp_as_buffer*/
1124
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,   /*tp_flags*/
1125
    0,                                         /*tp_doc*/
1126
    (traverseproc)bytesiobuf_traverse,         /*tp_traverse*/
1127
    0,                                         /*tp_clear*/
1128
    0,                                         /*tp_richcompare*/
1129
    0,                                         /*tp_weaklistoffset*/
1130
    0,                                         /*tp_iter*/
1131
    0,                                         /*tp_iternext*/
1132
    0,                                         /*tp_methods*/
1133
    0,                                         /*tp_members*/
1134
    0,                                         /*tp_getset*/
1135
    0,                                         /*tp_base*/
1136
    0,                                         /*tp_dict*/
1137
    0,                                         /*tp_descr_get*/
1138
    0,                                         /*tp_descr_set*/
1139
    0,                                         /*tp_dictoffset*/
1140
    0,                                         /*tp_init*/
1141
    0,                                         /*tp_alloc*/
1142
    0,                                         /*tp_new*/
1143
};