Commit 7c7bcdd3 authored by Marius Wachtler's avatar Marius Wachtler

fix _PyTuple_Resize and a null pointer dereference in seqiter_next

parent 5bfa36db
# expected: reffail
# - unknown segfault
import unittest
from test import test_support
......
......@@ -116,7 +116,7 @@ Box* seqiter_next(Box* s) noexcept {
hasnext = seqreviterHasnext_capi(s);
else
RELEASE_ASSERT(0, "");
AUTO_DECREF(hasnext);
AUTO_XDECREF(hasnext);
if (hasnext != True)
return NULL;
}
......
......@@ -116,29 +116,53 @@ extern "C" int _PyTuple_Resize(PyObject** pv, Py_ssize_t newsize) noexcept {
}
int BoxedTuple::Resize(BoxedTuple** pv, size_t newsize) noexcept {
assert((*pv)->cls == tuple_cls);
BoxedTuple* t = static_cast<BoxedTuple*>(*pv);
size_t oldsize = t->size();
if (newsize == oldsize)
return 0;
// cpythons _PyTuple_Resize with small s/PyTupleObject/BoxedTuple modifications
BoxedTuple* v;
BoxedTuple* sv;
Py_ssize_t i;
Py_ssize_t oldsize;
if (newsize < oldsize) {
// XXX resize the box (by reallocating) smaller if it makes sense
t->ob_size = newsize;
for (int i = newsize; i < oldsize; i++) {
Py_CLEAR((*pv)->elts[i]);
}
return 0;
v = *pv;
if (v == NULL || v->cls != &PyTuple_Type || (Py_SIZE(v) != 0 && Py_REFCNT(v) != 1)) {
*pv = 0;
Py_XDECREF(v);
PyErr_BadInternalCall();
return -1;
}
oldsize = Py_SIZE(v);
if (oldsize == newsize)
return 0;
BoxedTuple* resized = new (newsize) BoxedTuple();
memmove(resized->elts, t->elts, sizeof(Box*) * oldsize);
memset(resized->elts + oldsize, 0, sizeof(Box*) * (newsize - oldsize));
*pv = resized;
if (oldsize == 0) {
/* Empty tuples are often shared, so we should never
resize them in-place even if we do own the only
(current) reference */
Py_DECREF(v);
*pv = (BoxedTuple*)PyTuple_New(newsize);
return *pv == NULL ? -1 : 0;
}
/* XXX UNREF/NEWREF interface should be more symmetrical */
_Py_DEC_REFTOTAL;
if (_PyObject_GC_IS_TRACKED(v))
_PyObject_GC_UNTRACK(v);
_Py_ForgetReference((PyObject*)v);
/* DECREF items deleted by shrinkage */
for (i = newsize; i < oldsize; i++) {
Py_CLEAR(v->elts[i]);
}
sv = PyObject_GC_Resize(BoxedTuple, v, newsize);
if (sv == NULL) {
*pv = NULL;
PyObject_GC_Del(v);
return -1;
}
_Py_NewReference((PyObject*)sv);
/* Zero out items added by growing */
if (newsize > oldsize)
memset(&sv->elts[oldsize], 0, sizeof(*sv->elts) * (newsize - oldsize));
*pv = sv;
_PyObject_GC_TRACK(sv);
return 0;
}
......
......@@ -260,3 +260,6 @@ try:
print((1, 2) * d)
except TypeError as e:
print(e.message)
# this triggers a tuple resize because generators have a unknown len:
print len(tuple(v*10 for v in range(100)))
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