Mercurial > cpython-lru_cache-weakref
comparison Modules/arraymodule.c @ 50214:aebf7124dd32 3.0
Merged revisions 67840 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r67840 | antoine.pitrou | 2008-12-18 18:08:32 +0100 (jeu., 18 déc. 2008) | 3 lines
Issue #4583: crash after resizing an array.array which has buffer exports.
........
| author | Antoine Pitrou <solipsis@pitrou.net> |
|---|---|
| date | Thu, 18 Dec 2008 17:14:35 +0000 |
| parents | cd3b0b7fd8e1 |
| children | 87fbbf22adf3 |
comparison
equal
deleted
inserted
replaced
| 50203:d06b04c57b53 | 50214:aebf7124dd32 |
|---|---|
| 47 array_resize(arrayobject *self, Py_ssize_t newsize) | 47 array_resize(arrayobject *self, Py_ssize_t newsize) |
| 48 { | 48 { |
| 49 char *items; | 49 char *items; |
| 50 size_t _new_size; | 50 size_t _new_size; |
| 51 | 51 |
| 52 if (self->ob_exports > 0 && newsize != Py_SIZE(self)) { | |
| 53 PyErr_SetString(PyExc_BufferError, | |
| 54 "cannot resize an array that is exporting buffers"); | |
| 55 return -1; | |
| 56 } | |
| 57 | |
| 52 /* Bypass realloc() when a previous overallocation is large enough | 58 /* Bypass realloc() when a previous overallocation is large enough |
| 53 to accommodate the newsize. If the newsize is 16 smaller than the | 59 to accommodate the newsize. If the newsize is 16 smaller than the |
| 54 current size, then proceed with the realloc() to shrink the list. | 60 current size, then proceed with the realloc() to shrink the array. |
| 55 */ | 61 */ |
| 56 | 62 |
| 57 if (self->allocated >= newsize && | 63 if (self->allocated >= newsize && |
| 58 Py_SIZE(self) < newsize + 16 && | 64 Py_SIZE(self) < newsize + 16 && |
| 59 self->ob_item != NULL) { | 65 self->ob_item != NULL) { |
| 60 Py_SIZE(self) = newsize; | 66 Py_SIZE(self) = newsize; |
| 61 return 0; | 67 return 0; |
| 62 } | 68 } |
| 63 | 69 |
| 64 if (self->ob_exports > 0) { | 70 if (newsize == 0) { |
| 65 PyErr_SetString(PyExc_BufferError, | 71 PyMem_FREE(self->ob_item); |
| 66 "cannot resize an array that is exporting data"); | 72 self->ob_item = NULL; |
| 67 return -1; | 73 Py_SIZE(self) = 0; |
| 68 } | 74 self->allocated = 0; |
| 75 return 0; | |
| 76 } | |
| 69 | 77 |
| 70 /* This over-allocates proportional to the array size, making room | 78 /* This over-allocates proportional to the array size, making room |
| 71 * for additional growth. The over-allocation is mild, but is | 79 * for additional growth. The over-allocation is mild, but is |
| 72 * enough to give linear-time amortized behavior over a long | 80 * enough to give linear-time amortized behavior over a long |
| 73 * sequence of appends() in the presence of a poorly-performing | 81 * sequence of appends() in the presence of a poorly-performing |
| 729 d = n - (ihigh-ilow); | 737 d = n - (ihigh-ilow); |
| 730 if (d < 0) { /* Delete -d items */ | 738 if (d < 0) { /* Delete -d items */ |
| 731 memmove(item + (ihigh+d)*a->ob_descr->itemsize, | 739 memmove(item + (ihigh+d)*a->ob_descr->itemsize, |
| 732 item + ihigh*a->ob_descr->itemsize, | 740 item + ihigh*a->ob_descr->itemsize, |
| 733 (Py_SIZE(a)-ihigh)*a->ob_descr->itemsize); | 741 (Py_SIZE(a)-ihigh)*a->ob_descr->itemsize); |
| 734 Py_SIZE(a) += d; | 742 if (array_resize(a, Py_SIZE(a) + d) == -1) |
| 735 PyMem_RESIZE(item, char, Py_SIZE(a)*a->ob_descr->itemsize); | 743 return -1; |
| 736 /* Can't fail */ | |
| 737 a->ob_item = item; | |
| 738 a->allocated = Py_SIZE(a); | |
| 739 } | 744 } |
| 740 else if (d > 0) { /* Insert d items */ | 745 else if (d > 0) { /* Insert d items */ |
| 741 PyMem_RESIZE(item, char, | 746 if (array_resize(a, Py_SIZE(a) + d)) |
| 742 (Py_SIZE(a) + d)*a->ob_descr->itemsize); | |
| 743 if (item == NULL) { | |
| 744 PyErr_NoMemory(); | |
| 745 return -1; | 747 return -1; |
| 746 } | |
| 747 memmove(item + (ihigh+d)*a->ob_descr->itemsize, | 748 memmove(item + (ihigh+d)*a->ob_descr->itemsize, |
| 748 item + ihigh*a->ob_descr->itemsize, | 749 item + ihigh*a->ob_descr->itemsize, |
| 749 (Py_SIZE(a)-ihigh)*a->ob_descr->itemsize); | 750 (Py_SIZE(a)-ihigh)*a->ob_descr->itemsize); |
| 750 a->ob_item = item; | |
| 751 Py_SIZE(a) += d; | |
| 752 a->allocated = Py_SIZE(a); | |
| 753 } | 751 } |
| 754 if (n > 0) | 752 if (n > 0) |
| 755 memcpy(item + ilow*a->ob_descr->itemsize, b->ob_item, | 753 memcpy(item + ilow*a->ob_descr->itemsize, b->ob_item, |
| 756 n*b->ob_descr->itemsize); | 754 n*b->ob_descr->itemsize); |
| 757 return 0; | 755 return 0; |
| 802 } | 800 } |
| 803 | 801 |
| 804 static int | 802 static int |
| 805 array_do_extend(arrayobject *self, PyObject *bb) | 803 array_do_extend(arrayobject *self, PyObject *bb) |
| 806 { | 804 { |
| 807 Py_ssize_t size; | 805 Py_ssize_t size, oldsize; |
| 808 char *old_item; | |
| 809 | 806 |
| 810 if (!array_Check(bb)) | 807 if (!array_Check(bb)) |
| 811 return array_iter_extend(self, bb); | 808 return array_iter_extend(self, bb); |
| 812 #define b ((arrayobject *)bb) | 809 #define b ((arrayobject *)bb) |
| 813 if (self->ob_descr != b->ob_descr) { | 810 if (self->ob_descr != b->ob_descr) { |
| 818 if ((Py_SIZE(self) > PY_SSIZE_T_MAX - Py_SIZE(b)) || | 815 if ((Py_SIZE(self) > PY_SSIZE_T_MAX - Py_SIZE(b)) || |
| 819 ((Py_SIZE(self) + Py_SIZE(b)) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) { | 816 ((Py_SIZE(self) + Py_SIZE(b)) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) { |
| 820 PyErr_NoMemory(); | 817 PyErr_NoMemory(); |
| 821 return -1; | 818 return -1; |
| 822 } | 819 } |
| 823 size = Py_SIZE(self) + Py_SIZE(b); | 820 oldsize = Py_SIZE(self); |
| 824 old_item = self->ob_item; | 821 size = oldsize + Py_SIZE(b); |
| 825 PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize); | 822 if (array_resize(self, size) == -1) |
| 826 if (self->ob_item == NULL) { | 823 return -1; |
| 827 self->ob_item = old_item; | 824 memcpy(self->ob_item + oldsize * self->ob_descr->itemsize, |
| 828 PyErr_NoMemory(); | 825 b->ob_item, Py_SIZE(b) * b->ob_descr->itemsize); |
| 829 return -1; | |
| 830 } | |
| 831 memcpy(self->ob_item + Py_SIZE(self)*self->ob_descr->itemsize, | |
| 832 b->ob_item, Py_SIZE(b)*b->ob_descr->itemsize); | |
| 833 Py_SIZE(self) = size; | |
| 834 self->allocated = size; | |
| 835 | 826 |
| 836 return 0; | 827 return 0; |
| 837 #undef b | 828 #undef b |
| 838 } | 829 } |
| 839 | 830 |
| 865 if ((self->ob_descr->itemsize != 0) && | 856 if ((self->ob_descr->itemsize != 0) && |
| 866 (Py_SIZE(self) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) { | 857 (Py_SIZE(self) > PY_SSIZE_T_MAX / self->ob_descr->itemsize)) { |
| 867 return PyErr_NoMemory(); | 858 return PyErr_NoMemory(); |
| 868 } | 859 } |
| 869 size = Py_SIZE(self) * self->ob_descr->itemsize; | 860 size = Py_SIZE(self) * self->ob_descr->itemsize; |
| 870 if (n == 0) { | 861 if (n > 0 && size > PY_SSIZE_T_MAX / n) { |
| 871 PyMem_FREE(items); | 862 return PyErr_NoMemory(); |
| 872 self->ob_item = NULL; | 863 } |
| 873 Py_SIZE(self) = 0; | 864 if (array_resize(self, n * Py_SIZE(self)) == -1) |
| 874 self->allocated = 0; | 865 return NULL; |
| 875 } | 866 items = p = self->ob_item; |
| 876 else { | 867 for (i = 1; i < n; i++) { |
| 877 if (size > PY_SSIZE_T_MAX / n) { | 868 p += size; |
| 878 return PyErr_NoMemory(); | 869 memcpy(p, items, size); |
| 879 } | |
| 880 PyMem_RESIZE(items, char, n * size); | |
| 881 if (items == NULL) | |
| 882 return PyErr_NoMemory(); | |
| 883 p = items; | |
| 884 for (i = 1; i < n; i++) { | |
| 885 p += size; | |
| 886 memcpy(p, items, size); | |
| 887 } | |
| 888 self->ob_item = items; | |
| 889 Py_SIZE(self) *= n; | |
| 890 self->allocated = Py_SIZE(self); | |
| 891 } | 870 } |
| 892 } | 871 } |
| 893 Py_INCREF(self); | 872 Py_INCREF(self); |
| 894 return (PyObject *)self; | 873 return (PyObject *)self; |
| 895 } | 874 } |
| 1310 | 1289 |
| 1311 static PyObject * | 1290 static PyObject * |
| 1312 array_fromlist(arrayobject *self, PyObject *list) | 1291 array_fromlist(arrayobject *self, PyObject *list) |
| 1313 { | 1292 { |
| 1314 Py_ssize_t n; | 1293 Py_ssize_t n; |
| 1315 Py_ssize_t itemsize = self->ob_descr->itemsize; | |
| 1316 | 1294 |
| 1317 if (!PyList_Check(list)) { | 1295 if (!PyList_Check(list)) { |
| 1318 PyErr_SetString(PyExc_TypeError, "arg must be list"); | 1296 PyErr_SetString(PyExc_TypeError, "arg must be list"); |
| 1319 return NULL; | 1297 return NULL; |
| 1320 } | 1298 } |
| 1321 n = PyList_Size(list); | 1299 n = PyList_Size(list); |
| 1322 if (n > 0) { | 1300 if (n > 0) { |
| 1323 char *item = self->ob_item; | 1301 Py_ssize_t i, old_size; |
| 1324 Py_ssize_t i; | 1302 old_size = Py_SIZE(self); |
| 1325 PyMem_RESIZE(item, char, (Py_SIZE(self) + n) * itemsize); | 1303 if (array_resize(self, old_size + n) == -1) |
| 1326 if (item == NULL) { | |
| 1327 PyErr_NoMemory(); | |
| 1328 return NULL; | 1304 return NULL; |
| 1329 } | |
| 1330 self->ob_item = item; | |
| 1331 Py_SIZE(self) += n; | |
| 1332 self->allocated = Py_SIZE(self); | |
| 1333 for (i = 0; i < n; i++) { | 1305 for (i = 0; i < n; i++) { |
| 1334 PyObject *v = PyList_GetItem(list, i); | 1306 PyObject *v = PyList_GetItem(list, i); |
| 1335 if ((*self->ob_descr->setitem)(self, | 1307 if ((*self->ob_descr->setitem)(self, |
| 1336 Py_SIZE(self) - n + i, v) != 0) { | 1308 Py_SIZE(self) - n + i, v) != 0) { |
| 1337 Py_SIZE(self) -= n; | 1309 array_resize(self, old_size); |
| 1338 if (itemsize && (Py_SIZE(self) > PY_SSIZE_T_MAX / itemsize)) { | |
| 1339 return PyErr_NoMemory(); | |
| 1340 } | |
| 1341 PyMem_RESIZE(item, char, | |
| 1342 Py_SIZE(self) * itemsize); | |
| 1343 self->ob_item = item; | |
| 1344 self->allocated = Py_SIZE(self); | |
| 1345 return NULL; | 1310 return NULL; |
| 1346 } | 1311 } |
| 1347 } | 1312 } |
| 1348 } | 1313 } |
| 1349 Py_INCREF(Py_None); | 1314 Py_INCREF(Py_None); |
| 1393 "string length not a multiple of item size"); | 1358 "string length not a multiple of item size"); |
| 1394 return NULL; | 1359 return NULL; |
| 1395 } | 1360 } |
| 1396 n = n / itemsize; | 1361 n = n / itemsize; |
| 1397 if (n > 0) { | 1362 if (n > 0) { |
| 1398 char *item = self->ob_item; | 1363 Py_ssize_t old_size = Py_SIZE(self); |
| 1399 if ((n > PY_SSIZE_T_MAX - Py_SIZE(self)) || | 1364 if ((n > PY_SSIZE_T_MAX - old_size) || |
| 1400 ((Py_SIZE(self) + n) > PY_SSIZE_T_MAX / itemsize)) { | 1365 ((old_size + n) > PY_SSIZE_T_MAX / itemsize)) { |
| 1401 return PyErr_NoMemory(); | 1366 return PyErr_NoMemory(); |
| 1402 } | 1367 } |
| 1403 PyMem_RESIZE(item, char, (Py_SIZE(self) + n) * itemsize); | 1368 if (array_resize(self, old_size + n) == -1) |
| 1404 if (item == NULL) { | |
| 1405 PyErr_NoMemory(); | |
| 1406 return NULL; | 1369 return NULL; |
| 1407 } | 1370 memcpy(self->ob_item + old_size * itemsize, |
| 1408 self->ob_item = item; | 1371 str, n * itemsize); |
| 1409 Py_SIZE(self) += n; | |
| 1410 self->allocated = Py_SIZE(self); | |
| 1411 memcpy(item + (Py_SIZE(self) - n) * itemsize, | |
| 1412 str, itemsize*n); | |
| 1413 } | 1372 } |
| 1414 Py_INCREF(Py_None); | 1373 Py_INCREF(Py_None); |
| 1415 return Py_None; | 1374 return Py_None; |
| 1416 } | 1375 } |
| 1417 | 1376 |
| 1456 "fromunicode() may only be called on " | 1415 "fromunicode() may only be called on " |
| 1457 "unicode type arrays"); | 1416 "unicode type arrays"); |
| 1458 return NULL; | 1417 return NULL; |
| 1459 } | 1418 } |
| 1460 if (n > 0) { | 1419 if (n > 0) { |
| 1461 Py_UNICODE *item = (Py_UNICODE *) self->ob_item; | 1420 Py_ssize_t old_size = Py_SIZE(self); |
| 1462 if (Py_SIZE(self) > PY_SSIZE_T_MAX - n) { | 1421 if (array_resize(self, old_size + n) == -1) |
| 1463 return PyErr_NoMemory(); | |
| 1464 } | |
| 1465 PyMem_RESIZE(item, Py_UNICODE, Py_SIZE(self) + n); | |
| 1466 if (item == NULL) { | |
| 1467 PyErr_NoMemory(); | |
| 1468 return NULL; | 1422 return NULL; |
| 1469 } | 1423 memcpy(self->ob_item + old_size * sizeof(Py_UNICODE), |
| 1470 self->ob_item = (char *) item; | |
| 1471 Py_SIZE(self) += n; | |
| 1472 self->allocated = Py_SIZE(self); | |
| 1473 memcpy(item + Py_SIZE(self) - n, | |
| 1474 ustr, n * sizeof(Py_UNICODE)); | 1424 ustr, n * sizeof(Py_UNICODE)); |
| 1475 } | 1425 } |
| 1476 | 1426 |
| 1477 Py_INCREF(Py_None); | 1427 Py_INCREF(Py_None); |
| 1478 return Py_None; | 1428 return Py_None; |
| 1738 if (slicelength > needed) { | 1688 if (slicelength > needed) { |
| 1739 memmove(self->ob_item + (start + needed) * itemsize, | 1689 memmove(self->ob_item + (start + needed) * itemsize, |
| 1740 self->ob_item + stop * itemsize, | 1690 self->ob_item + stop * itemsize, |
| 1741 (Py_SIZE(self) - stop) * itemsize); | 1691 (Py_SIZE(self) - stop) * itemsize); |
| 1742 if (array_resize(self, Py_SIZE(self) + | 1692 if (array_resize(self, Py_SIZE(self) + |
| 1743 needed - slicelength) < 0) | 1693 needed - slicelength) < 0) |
| 1744 return -1; | 1694 return -1; |
| 1745 } | 1695 } |
| 1746 else if (slicelength < needed) { | 1696 else if (slicelength < needed) { |
| 1747 if (array_resize(self, Py_SIZE(self) + | 1697 if (array_resize(self, Py_SIZE(self) + |
| 1748 needed - slicelength) < 0) | 1698 needed - slicelength) < 0) |
| 1749 return -1; | 1699 return -1; |
| 1750 memmove(self->ob_item + (start + needed) * itemsize, | 1700 memmove(self->ob_item + (start + needed) * itemsize, |
| 1751 self->ob_item + stop * itemsize, | 1701 self->ob_item + stop * itemsize, |
| 1752 (Py_SIZE(self) - start - needed) * itemsize); | 1702 (Py_SIZE(self) - start - needed) * itemsize); |
| 1753 } | 1703 } |
