fix reentrancy bug in slice assignment

This commit is contained in:
Guido van Rossum 1995-01-17 10:21:11 +00:00
parent ba0b6aeda6
commit ae7bf1a5e7

View file

@ -368,6 +368,13 @@ list_ass_slice(a, ilow, ihigh, v)
int ilow, ihigh;
object *v;
{
/* Because [X]DECREF can recursively invoke list operations on
this list, we must postpone all [X]DECREF activity until
after the list is back in its canonical shape. Therefore
we must allocate an additional array, 'recycle', into which
we temporarily copy the items that are deleted from the
list. :-( */
object **recycle, **p;
object **item;
int n; /* Size of replacement list */
int d; /* Change in size */
@ -402,9 +409,13 @@ list_ass_slice(a, ilow, ihigh, v)
ihigh = a->ob_size;
item = a->ob_item;
d = n - (ihigh-ilow);
if (d <= 0) { /* Delete -d items; XDECREF ihigh-ilow items */
if (ihigh > ilow)
p = recycle = NEW(object *, (ihigh-ilow));
else
p = recycle = NULL;
if (d <= 0) { /* Delete -d items; recycle ihigh-ilow items */
for (k = ilow; k < ihigh; k++)
XDECREF(item[k]); /* bug: reentrant side effects */
*p++ = item[k];
if (d < 0) {
for (/*k = ihigh*/; k < a->ob_size; k++)
item[k+d] = item[k];
@ -413,7 +424,7 @@ list_ass_slice(a, ilow, ihigh, v)
a->ob_item = item;
}
}
else { /* Insert d items; XDECREF ihigh-ilow items */
else { /* Insert d items; recycle ihigh-ilow items */
RESIZE(item, object *, a->ob_size + d);
if (item == NULL) {
err_nomem();
@ -422,7 +433,7 @@ list_ass_slice(a, ilow, ihigh, v)
for (k = a->ob_size; --k >= ihigh; )
item[k+d] = item[k];
for (/*k = ihigh-1*/; k >= ilow; --k)
XDECREF(item[k]); /* bug: side effects :-( */
*p++ = item[k];
a->ob_item = item;
a->ob_size += d;
}
@ -431,6 +442,11 @@ list_ass_slice(a, ilow, ihigh, v)
XINCREF(w);
item[ilow] = w;
}
if (recycle) {
while (--p >= recycle)
XDECREF(*p);
DEL(recycle);
}
return 0;
#undef b
}