self.assertEqual(buf[3:], bytesIo.read())
self.assertRaises(TypeError, bytesIo.seek, 0.0)
+ self.assertEqual(sys.maxsize, bytesIo.seek(sys.maxsize))
+ self.assertEqual(self.EOF, bytesIo.read(4))
+
+ self.assertEqual(sys.maxsize - 2, bytesIo.seek(sys.maxsize - 2))
+ self.assertEqual(self.EOF, bytesIo.read(4))
+
def testTell(self):
buf = self.buftype("1234567890")
bytesIo = self.ioclass(buf)
memio.seek(1, 1)
self.assertEqual(memio.read(), buf[1:])
+ def test_issue141311(self):
+ memio = self.ioclass()
+ # Seek allows PY_SSIZE_T_MAX, read should handle that.
+ # Past end of buffer read should always return 0 (EOF).
+ self.assertEqual(sys.maxsize, memio.seek(sys.maxsize))
+ buf = bytearray(2)
+ self.assertEqual(0, memio.readinto(buf))
+
def test_unicode(self):
memio = self.ioclass()
return Py_NewRef(self->buf);
}
+ /* gh-141311: Avoid undefined behavior when self->pos (limit PY_SSIZE_T_MAX)
+ is beyond the size of self->buf. Assert above validates size is always in
+ bounds. When self->pos is out of bounds calling code sets size to 0. */
+ if (size == 0) {
+ return PyBytes_FromStringAndSize(NULL, 0);
+ }
+
output = PyBytes_AS_STRING(self->buf) + self->pos;
self->pos += size;
return PyBytes_FromStringAndSize(output, size);
n = self->string_size - self->pos;
if (len > n) {
len = n;
- if (len < 0)
- len = 0;
+ if (len < 0) {
+ /* gh-141311: Avoid undefined behavior when self->pos (limit
+ PY_SSIZE_T_MAX) points beyond the size of self->buf. */
+ return PyLong_FromSsize_t(0);
+ }
}
- assert(self->pos + len < PY_SSIZE_T_MAX);
+ assert(self->pos + len <= PY_SSIZE_T_MAX);
assert(len >= 0);
memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
self->pos += len;