| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -536,6 +536,22 @@ def test_readline(self): | |||
| 536 | 536 | with self.open(support.TESTFN, "r") as f: | |
| 537 | 537 | self.assertRaises(TypeError, f.readline, 5.3) | |
| 538 | 538 | ||
| 539 | + def test_readline_nonsizeable(self): | ||
| 540 | + # Issue #30061 | ||
| 541 | + # Crash when readline() returns an object without __len__ | ||
| 542 | + class R(self.IOBase): | ||
| 543 | + def readline(self): | ||
| 544 | + return None | ||
| 545 | + self.assertRaises((TypeError, StopIteration), next, R()) | ||
| 546 | + | ||
| 547 | + def test_next_nonsizeable(self): | ||
| 548 | + # Issue #30061 | ||
| 549 | + # Crash when __next__() returns an object without __len__ | ||
| 550 | + class R(self.IOBase): | ||
| 551 | + def __next__(self): | ||
| 552 | + return None | ||
| 553 | + self.assertRaises(TypeError, R().readlines, 1) | ||
| 554 | + | ||
| 539 | 555 | def test_raw_bytes_io(self): | |
| 540 | 556 | f = self.BytesIO() | |
| 541 | 557 | self.write_ops(f) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -49,6 +49,11 @@ Extension Modules | |||
| 49 | 49 | Library | |
| 50 | 50 | ------- | |
| 51 | 51 | ||
| 52 | + - bpo-30061: Fixed crashes in IOBase methods __next__() and readlines() when | ||
| 53 | + readline() or __next__() respectively return non-sizeable object. | ||
| 54 | + Fixed possible other errors caused by not checking results of PyObject_Size(), | ||
| 55 | + PySequence_Size(), or PyMapping_Size(). | ||
| 56 | + | ||
| 52 | 57 | - bpo-30068: _io._IOBase.readlines will check if it's closed first when | |
| 53 | 58 | hint is present. | |
| 54 | 59 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -625,7 +625,8 @@ iobase_iternext(PyObject *self) | |||
| 625 | 625 | if (line == NULL) | |
| 626 | 626 | return NULL; | |
| 627 | 627 | ||
| 628 | - if (PyObject_Size(line) == 0) { | ||
| 628 | + if (PyObject_Size(line) <= 0) { | ||
| 629 | + /* Error or empty */ | ||
| 629 | 630 | Py_DECREF(line); | |
| 630 | 631 | return NULL; | |
| 631 | 632 | } | |
@@ -676,6 +677,7 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint) | |||
| 676 | 677 | } | |
| 677 | 678 | ||
| 678 | 679 | while (1) { | |
| 680 | + Py_ssize_t line_length; | ||
| 679 | 681 | PyObject *line = PyIter_Next(it); | |
| 680 | 682 | if (line == NULL) { | |
| 681 | 683 | if (PyErr_Occurred()) { | |
@@ -689,11 +691,14 @@ _io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint) | |||
| 689 | 691 | Py_DECREF(line); | |
| 690 | 692 | goto error; | |
| 691 | 693 | } | |
| 692 | - length += PyObject_Size(line); | ||
| 694 | + line_length = PyObject_Size(line); | ||
| 693 | 695 | Py_DECREF(line); | |
| 694 | - | ||
| 695 | - if (length > hint) | ||
| 696 | + if (line_length < 0) { | ||
| 697 | + goto error; | ||
| 698 | + } | ||
| 699 | + if (line_length > hint - length) | ||
| 696 | 700 | break; | |
| 701 | + length += line_length; | ||
| 697 | 702 | } | |
| 698 | 703 | ||
| 699 | 704 | Py_DECREF(it); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -722,17 +722,22 @@ getenvironment(PyObject* environment) | |||
| 722 | 722 | return NULL; | |
| 723 | 723 | } | |
| 724 | 724 | ||
| 725 | - envsize = PyMapping_Length(environment); | ||
| 726 | - | ||
| 727 | 725 | keys = PyMapping_Keys(environment); | |
| 728 | 726 | values = PyMapping_Values(environment); | |
| 729 | 727 | if (!keys || !values) | |
| 730 | 728 | goto error; | |
| 731 | 729 | ||
| 730 | + envsize = PySequence_Fast_GET_SIZE(keys); | ||
| 731 | + if (PySequence_Fast_GET_SIZE(values) != envsize) { | ||
| 732 | + PyErr_SetString(PyExc_RuntimeError, | ||
| 733 | + "environment changed size during iteration"); | ||
| 734 | + goto error; | ||
| 735 | + } | ||
| 736 | + | ||
| 732 | 737 | totalsize = 1; /* trailing null character */ | |
| 733 | 738 | for (i = 0; i < envsize; i++) { | |
| 734 | - PyObject* key = PyList_GET_ITEM(keys, i); | ||
| 735 | - PyObject* value = PyList_GET_ITEM(values, i); | ||
| 739 | + PyObject* key = PySequence_Fast_GET_ITEM(keys, i); | ||
| 740 | + PyObject* value = PySequence_Fast_GET_ITEM(values, i); | ||
| 736 | 741 | ||
| 737 | 742 | if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) { | |
| 738 | 743 | PyErr_SetString(PyExc_TypeError, | |
@@ -760,8 +765,8 @@ getenvironment(PyObject* environment) | |||
| 760 | 765 | end = buffer + totalsize; | |
| 761 | 766 | ||
| 762 | 767 | for (i = 0; i < envsize; i++) { | |
| 763 | - PyObject* key = PyList_GET_ITEM(keys, i); | ||
| 764 | - PyObject* value = PyList_GET_ITEM(values, i); | ||
| 768 | + PyObject* key = PySequence_Fast_GET_ITEM(keys, i); | ||
| 769 | + PyObject* value = PySequence_Fast_GET_ITEM(values, i); | ||
| 765 | 770 | if (!PyUnicode_AsUCS4(key, p, end - p, 0)) | |
| 766 | 771 | goto error; | |
| 767 | 772 | p += PyUnicode_GET_LENGTH(key); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1670,6 +1670,9 @@ _multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *se | |||
| 1670 | 1670 | if (r == -1) | |
| 1671 | 1671 | return NULL; | |
| 1672 | 1672 | } | |
| 1673 | + /* PySequence_Length() can fail */ | ||
| 1674 | + if (PyErr_Occurred()) | ||
| 1675 | + return NULL; | ||
| 1673 | 1676 | ||
| 1674 | 1677 | Py_RETURN_NONE; | |
| 1675 | 1678 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6755,14 +6755,17 @@ static PyObject * | |||
| 6755 | 6755 | os_setgroups(PyObject *module, PyObject *groups) | |
| 6756 | 6756 | /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/ | |
| 6757 | 6757 | { | |
| 6758 | - int i, len; | ||
| 6758 | + Py_ssize_t i, len; | ||
| 6759 | 6759 | gid_t grouplist[MAX_GROUPS]; | |
| 6760 | 6760 | ||
| 6761 | 6761 | if (!PySequence_Check(groups)) { | |
| 6762 | 6762 | PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); | |
| 6763 | 6763 | return NULL; | |
| 6764 | 6764 | } | |
| 6765 | 6765 | len = PySequence_Size(groups); | |
| 6766 | + if (len < 0) { | ||
| 6767 | + return NULL; | ||
| 6768 | + } | ||
| 6766 | 6769 | if (len > MAX_GROUPS) { | |
| 6767 | 6770 | PyErr_SetString(PyExc_ValueError, "too many groups"); | |
| 6768 | 6771 | return NULL; | |
@@ -8076,9 +8079,9 @@ os_read_impl(PyObject *module, int fd, Py_ssize_t length) | |||
| 8076 | 8079 | #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ | |
| 8077 | 8080 | || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV) | |
| 8078 | 8081 | static Py_ssize_t | |
| 8079 | - iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) | ||
| 8082 | + iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type) | ||
| 8080 | 8083 | { | |
| 8081 | - int i, j; | ||
| 8084 | + Py_ssize_t i, j; | ||
| 8082 | 8085 | Py_ssize_t blen, total = 0; | |
| 8083 | 8086 | ||
| 8084 | 8087 | *iov = PyMem_New(struct iovec, cnt); | |
@@ -8155,8 +8158,7 @@ static Py_ssize_t | |||
| 8155 | 8158 | os_readv_impl(PyObject *module, int fd, PyObject *buffers) | |
| 8156 | 8159 | /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/ | |
| 8157 | 8160 | { | |
| 8158 | - int cnt; | ||
| 8159 | - Py_ssize_t n; | ||
| 8161 | + Py_ssize_t cnt, n; | ||
| 8160 | 8162 | int async_err = 0; | |
| 8161 | 8163 | struct iovec *iov; | |
| 8162 | 8164 | Py_buffer *buf; | |
@@ -8168,6 +8170,8 @@ os_readv_impl(PyObject *module, int fd, PyObject *buffers) | |||
| 8168 | 8170 | } | |
| 8169 | 8171 | ||
| 8170 | 8172 | cnt = PySequence_Size(buffers); | |
| 8173 | + if (cnt < 0) | ||
| 8174 | + return -1; | ||
| 8171 | 8175 | ||
| 8172 | 8176 | if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) | |
| 8173 | 8177 | return -1; | |
@@ -8310,15 +8314,24 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict) | |||
| 8310 | 8314 | "sendfile() headers must be a sequence"); | |
| 8311 | 8315 | return NULL; | |
| 8312 | 8316 | } else { | |
| 8313 | - Py_ssize_t i = 0; /* Avoid uninitialized warning */ | ||
| 8314 | - sf.hdr_cnt = PySequence_Size(headers); | ||
| 8315 | - if (sf.hdr_cnt > 0 && | ||
| 8316 | - (i = iov_setup(&(sf.headers), &hbuf, | ||
| 8317 | - headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0) | ||
| 8317 | + Py_ssize_t i = PySequence_Size(headers); | ||
| 8318 | + if (i < 0) | ||
| 8319 | + return NULL; | ||
| 8320 | + if (i > INT_MAX) { | ||
| 8321 | + PyErr_SetString(PyExc_OverflowError, | ||
| 8322 | + "sendfile() header is too large"); | ||
| 8318 | 8323 | return NULL; | |
| 8324 | + } | ||
| 8325 | + if (i > 0) { | ||
| 8326 | + sf.hdr_cnt = (int)i; | ||
| 8327 | + i = iov_setup(&(sf.headers), &hbuf, | ||
| 8328 | + headers, sf.hdr_cnt, PyBUF_SIMPLE); | ||
| 8329 | + if (i < 0) | ||
| 8330 | + return NULL; | ||
| 8319 | 8331 | #ifdef __APPLE__ | |
| 8320 | - sbytes += i; | ||
| 8332 | + sbytes += i; | ||
| 8321 | 8333 | #endif | |
| 8334 | + } | ||
| 8322 | 8335 | } | |
| 8323 | 8336 | } | |
| 8324 | 8337 | if (trailers != NULL) { | |
@@ -8327,15 +8340,24 @@ posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict) | |||
| 8327 | 8340 | "sendfile() trailers must be a sequence"); | |
| 8328 | 8341 | return NULL; | |
| 8329 | 8342 | } else { | |
| 8330 | - Py_ssize_t i = 0; /* Avoid uninitialized warning */ | ||
| 8331 | - sf.trl_cnt = PySequence_Size(trailers); | ||
| 8332 | - if (sf.trl_cnt > 0 && | ||
| 8333 | - (i = iov_setup(&(sf.trailers), &tbuf, | ||
| 8334 | - trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0) | ||
| 8343 | + Py_ssize_t i = PySequence_Size(trailers); | ||
| 8344 | + if (i < 0) | ||
| 8345 | + return NULL; | ||
| 8346 | + if (i > INT_MAX) { | ||
| 8347 | + PyErr_SetString(PyExc_OverflowError, | ||
| 8348 | + "sendfile() trailer is too large"); | ||
| 8335 | 8349 | return NULL; | |
| 8350 | + } | ||
| 8351 | + if (i > 0) { | ||
| 8352 | + sf.trl_cnt = (int)i; | ||
| 8353 | + i = iov_setup(&(sf.trailers), &tbuf, | ||
| 8354 | + trailers, sf.trl_cnt, PyBUF_SIMPLE); | ||
| 8355 | + if (i < 0) | ||
| 8356 | + return NULL; | ||
| 8336 | 8357 | #ifdef __APPLE__ | |
| 8337 | - sbytes += i; | ||
| 8358 | + sbytes += i; | ||
| 8338 | 8359 | #endif | |
| 8360 | + } | ||
| 8339 | 8361 | } | |
| 8340 | 8362 | } | |
| 8341 | 8363 | ||
@@ -8605,7 +8627,7 @@ static Py_ssize_t | |||
| 8605 | 8627 | os_writev_impl(PyObject *module, int fd, PyObject *buffers) | |
| 8606 | 8628 | /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/ | |
| 8607 | 8629 | { | |
| 8608 | - int cnt; | ||
| 8630 | + Py_ssize_t cnt; | ||
| 8609 | 8631 | Py_ssize_t result; | |
| 8610 | 8632 | int async_err = 0; | |
| 8611 | 8633 | struct iovec *iov; | |
@@ -8617,6 +8639,8 @@ os_writev_impl(PyObject *module, int fd, PyObject *buffers) | |||
| 8617 | 8639 | return -1; | |
| 8618 | 8640 | } | |
| 8619 | 8641 | cnt = PySequence_Size(buffers); | |
| 8642 | + if (cnt < 0) | ||
| 8643 | + return -1; | ||
| 8620 | 8644 | ||
| 8621 | 8645 | if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { | |
| 8622 | 8646 | return -1; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1498,15 +1498,21 @@ set_difference(PySetObject *so, PyObject *other) | |||
| 1498 | 1498 | { | |
| 1499 | 1499 | PyObject *result; | |
| 1500 | 1500 | setentry *entry; | |
| 1501 | - Py_ssize_t pos = 0; | ||
| 1501 | + Py_ssize_t pos = 0, other_size; | ||
| 1502 | 1502 | ||
| 1503 | - if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) { | ||
| 1503 | + if (PyAnySet_Check(other)) { | ||
| 1504 | + other_size = PySet_GET_SIZE(other); | ||
| 1505 | + } | ||
| 1506 | + else if (PyDict_CheckExact(other)) { | ||
| 1507 | + other_size = PyDict_Size(other); | ||
| 1508 | + } | ||
| 1509 | + else { | ||
| 1504 | 1510 | return set_copy_and_difference(so, other); | |
| 1505 | 1511 | } | |
| 1506 | 1512 | ||
| 1507 | 1513 | /* If len(so) much more than len(other), it's more efficient to simply copy | |
| 1508 | 1514 | * so and then iterate other looking for common elements. */ | |
| 1509 | - if ((PySet_GET_SIZE(so) >> 2) > PyObject_Size(other)) { | ||
| 1515 | + if ((PySet_GET_SIZE(so) >> 2) > other_size) { | ||
| 1510 | 1516 | return set_copy_and_difference(so, other); | |
| 1511 | 1517 | } | |
| 1512 | 1518 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments