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 }