Commit ae7bf1a5 authored by Guido van Rossum's avatar Guido van Rossum

fix reentrancy bug in slice assignment

parent ba0b6aed
......@@ -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
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment