mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
slot_nb_nonzero(): Another leak uncovered by the sandbox datetime
tests. I found the logic too confusing to follow here, so rewrote more than was likely absolutely necessary. Bugfix candidate.
This commit is contained in:
parent
27cae1f7c5
commit
ea7f75d423
1 changed files with 28 additions and 29 deletions
|
@ -43,7 +43,7 @@ type_name(PyTypeObject *type, void *context)
|
||||||
|
|
||||||
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
|
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
|
||||||
etype* et = (etype*)type;
|
etype* et = (etype*)type;
|
||||||
|
|
||||||
Py_INCREF(et->name);
|
Py_INCREF(et->name);
|
||||||
return et->name;
|
return et->name;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ type_set_name(PyTypeObject *type, PyObject *value, void *context)
|
||||||
type->tp_name, value->ob_type->tp_name);
|
type->tp_name, value->ob_type->tp_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (strlen(PyString_AS_STRING(value))
|
if (strlen(PyString_AS_STRING(value))
|
||||||
!= (size_t)PyString_GET_SIZE(value)) {
|
!= (size_t)PyString_GET_SIZE(value)) {
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"__name__ must not contain null bytes");
|
"__name__ must not contain null bytes");
|
||||||
|
@ -310,10 +310,10 @@ type_set_bases(PyTypeObject *type, PyObject *value, void *context)
|
||||||
type->tp_bases = old_bases;
|
type->tp_bases = old_bases;
|
||||||
type->tp_base = old_base;
|
type->tp_base = old_base;
|
||||||
type->tp_mro = old_mro;
|
type->tp_mro = old_mro;
|
||||||
|
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
Py_DECREF(new_base);
|
Py_DECREF(new_base);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,21 +884,21 @@ classic_mro(PyObject *cls)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Method resolution order algorithm C3 described in
|
Method resolution order algorithm C3 described in
|
||||||
"A Monotonic Superclass Linearization for Dylan",
|
"A Monotonic Superclass Linearization for Dylan",
|
||||||
by Kim Barrett, Bob Cassel, Paul Haahr,
|
by Kim Barrett, Bob Cassel, Paul Haahr,
|
||||||
David A. Moon, Keith Playford, and P. Tucker Withington.
|
David A. Moon, Keith Playford, and P. Tucker Withington.
|
||||||
(OOPSLA 1996)
|
(OOPSLA 1996)
|
||||||
|
|
||||||
Some notes about the rules implied by C3:
|
Some notes about the rules implied by C3:
|
||||||
|
|
||||||
No duplicate bases.
|
No duplicate bases.
|
||||||
It isn't legal to repeat a class in a list of base classes.
|
It isn't legal to repeat a class in a list of base classes.
|
||||||
|
|
||||||
The next three properties are the 3 constraints in "C3".
|
The next three properties are the 3 constraints in "C3".
|
||||||
|
|
||||||
Local precendece order.
|
Local precendece order.
|
||||||
If A precedes B in C's MRO, then A will precede B in the MRO of all
|
If A precedes B in C's MRO, then A will precede B in the MRO of all
|
||||||
subclasses of C.
|
subclasses of C.
|
||||||
|
|
||||||
|
@ -912,7 +912,7 @@ classic_mro(PyObject *cls)
|
||||||
the paper for definition of EPG.
|
the paper for definition of EPG.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tail_contains(PyObject *list, int whence, PyObject *o) {
|
tail_contains(PyObject *list, int whence, PyObject *o) {
|
||||||
int j, size;
|
int j, size;
|
||||||
size = PyList_GET_SIZE(list);
|
size = PyList_GET_SIZE(list);
|
||||||
|
@ -1010,12 +1010,12 @@ set_mro_error(PyObject *to_merge, int *remain)
|
||||||
Py_DECREF(set);
|
Py_DECREF(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pmerge(PyObject *acc, PyObject* to_merge) {
|
pmerge(PyObject *acc, PyObject* to_merge) {
|
||||||
int i, j, to_merge_size;
|
int i, j, to_merge_size;
|
||||||
int *remain;
|
int *remain;
|
||||||
int ok, empty_cnt;
|
int ok, empty_cnt;
|
||||||
|
|
||||||
to_merge_size = PyList_GET_SIZE(to_merge);
|
to_merge_size = PyList_GET_SIZE(to_merge);
|
||||||
|
|
||||||
/* remain stores an index into each sublist of to_merge.
|
/* remain stores an index into each sublist of to_merge.
|
||||||
|
@ -1032,7 +1032,7 @@ pmerge(PyObject *acc, PyObject* to_merge) {
|
||||||
empty_cnt = 0;
|
empty_cnt = 0;
|
||||||
for (i = 0; i < to_merge_size; i++) {
|
for (i = 0; i < to_merge_size; i++) {
|
||||||
PyObject *candidate;
|
PyObject *candidate;
|
||||||
|
|
||||||
PyObject *cur_list = PyList_GET_ITEM(to_merge, i);
|
PyObject *cur_list = PyList_GET_ITEM(to_merge, i);
|
||||||
|
|
||||||
if (remain[i] >= PyList_GET_SIZE(cur_list)) {
|
if (remain[i] >= PyList_GET_SIZE(cur_list)) {
|
||||||
|
@ -1092,7 +1092,7 @@ mro_implementation(PyTypeObject *type)
|
||||||
|
|
||||||
/* Find a superclass linearization that honors the constraints
|
/* Find a superclass linearization that honors the constraints
|
||||||
of the explicit lists of bases and the constraints implied by
|
of the explicit lists of bases and the constraints implied by
|
||||||
each base class.
|
each base class.
|
||||||
|
|
||||||
to_merge is a list of lists, where each list is a superclass
|
to_merge is a list of lists, where each list is a superclass
|
||||||
linearization implied by a base class. The last element of
|
linearization implied by a base class. The last element of
|
||||||
|
@ -2288,7 +2288,7 @@ compatible_for_assignment(PyTypeObject* old, PyTypeObject* new, char* attr)
|
||||||
old->tp_name);
|
old->tp_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2355,7 +2355,7 @@ object_reduce(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef object_methods[] = {
|
static PyMethodDef object_methods[] = {
|
||||||
{"__reduce__", object_reduce, METH_NOARGS,
|
{"__reduce__", object_reduce, METH_NOARGS,
|
||||||
PyDoc_STR("helper for pickle")},
|
PyDoc_STR("helper for pickle")},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
@ -3734,30 +3734,29 @@ SLOT0(slot_nb_absolute, "__abs__")
|
||||||
static int
|
static int
|
||||||
slot_nb_nonzero(PyObject *self)
|
slot_nb_nonzero(PyObject *self)
|
||||||
{
|
{
|
||||||
PyObject *func, *res, *args;
|
PyObject *func, *args;
|
||||||
static PyObject *nonzero_str, *len_str;
|
static PyObject *nonzero_str, *len_str;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
func = lookup_maybe(self, "__nonzero__", &nonzero_str);
|
func = lookup_maybe(self, "__nonzero__", &nonzero_str);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
func = lookup_maybe(self, "__len__", &len_str);
|
func = lookup_maybe(self, "__len__", &len_str);
|
||||||
if (func == NULL) {
|
if (func == NULL)
|
||||||
if (PyErr_Occurred())
|
return PyErr_Occurred() ? -1 : 1;
|
||||||
return -1;
|
}
|
||||||
else
|
args = PyTuple_New(0);
|
||||||
return 1;
|
if (args != NULL) {
|
||||||
|
PyObject *temp = PyObject_Call(func, args, NULL);
|
||||||
|
Py_DECREF(args);
|
||||||
|
if (temp != NULL) {
|
||||||
|
result = PyObject_IsTrue(temp);
|
||||||
|
Py_DECREF(temp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args = res = PyTuple_New(0);
|
|
||||||
if (args != NULL) {
|
|
||||||
res = PyObject_Call(func, args, NULL);
|
|
||||||
Py_DECREF(args);
|
|
||||||
}
|
|
||||||
Py_DECREF(func);
|
Py_DECREF(func);
|
||||||
if (res == NULL)
|
return result;
|
||||||
return -1;
|
|
||||||
return PyObject_IsTrue(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SLOT0(slot_nb_invert, "__invert__")
|
SLOT0(slot_nb_invert, "__invert__")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue