mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
Coredumpers from Michael Hudson, mutating dicts while printing or
converting to string. Critical bugfix candidate -- if you take this seriously <wink>.
This commit is contained in:
parent
89e90d67aa
commit
23cf6be23c
2 changed files with 84 additions and 8 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
from test_support import verbose
|
from test_support import verbose, TESTFN
|
||||||
import random
|
import random
|
||||||
|
import os
|
||||||
|
|
||||||
# From SF bug #422121: Insecurities in dict comparison.
|
# From SF bug #422121: Insecurities in dict comparison.
|
||||||
|
|
||||||
|
|
@ -151,3 +152,66 @@ def test(n):
|
||||||
|
|
||||||
# See last comment block for clues about good values for n.
|
# See last comment block for clues about good values for n.
|
||||||
test(100)
|
test(100)
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Another segfault bug, distilled by Micheal Hundson from a c.l.py post.
|
||||||
|
|
||||||
|
class Child:
|
||||||
|
def __init__(self, parent):
|
||||||
|
self.__dict__['parent'] = parent
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
self.parent.a = 1
|
||||||
|
self.parent.b = 1
|
||||||
|
self.parent.c = 1
|
||||||
|
self.parent.d = 1
|
||||||
|
self.parent.e = 1
|
||||||
|
self.parent.f = 1
|
||||||
|
self.parent.g = 1
|
||||||
|
self.parent.h = 1
|
||||||
|
self.parent.i = 1
|
||||||
|
return getattr(self.parent, attr)
|
||||||
|
|
||||||
|
class Parent:
|
||||||
|
def __init__(self):
|
||||||
|
self.a = Child(self)
|
||||||
|
|
||||||
|
# Hard to say what this will print! May vary from time to time. But
|
||||||
|
# we're specifically trying to test the tp_print slot here, and this is
|
||||||
|
# the clearest way to do it. We print the result to a temp file so that
|
||||||
|
# the expected-output file doesn't need to change.
|
||||||
|
|
||||||
|
f = open(TESTFN, "w")
|
||||||
|
print >> f, Parent().__dict__
|
||||||
|
f.close()
|
||||||
|
os.unlink(TESTFN)
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# And another core-dumper from Michael Hudson.
|
||||||
|
|
||||||
|
dict = {}
|
||||||
|
|
||||||
|
# Force dict to malloc its table.
|
||||||
|
for i in range(1, 10):
|
||||||
|
dict[i] = i
|
||||||
|
|
||||||
|
f = open(TESTFN, "w")
|
||||||
|
|
||||||
|
class Machiavelli:
|
||||||
|
def __repr__(self):
|
||||||
|
dict.clear()
|
||||||
|
|
||||||
|
# Michael sez: "doesn't crash without this. don't know why."
|
||||||
|
# Tim sez: "luck of the draw; crashes with or without for me."
|
||||||
|
print >> f
|
||||||
|
|
||||||
|
return `"machiavelli"`
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
dict[Machiavelli()] = Machiavelli()
|
||||||
|
|
||||||
|
print >> f, str(dict)
|
||||||
|
f.close()
|
||||||
|
os.unlink(TESTFN)
|
||||||
|
del f, dict
|
||||||
|
|
|
||||||
|
|
@ -740,7 +740,6 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags)
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
register int any;
|
register int any;
|
||||||
register dictentry *ep;
|
|
||||||
|
|
||||||
i = Py_ReprEnter((PyObject*)mp);
|
i = Py_ReprEnter((PyObject*)mp);
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
|
|
@ -752,19 +751,27 @@ dict_print(register dictobject *mp, register FILE *fp, register int flags)
|
||||||
|
|
||||||
fprintf(fp, "{");
|
fprintf(fp, "{");
|
||||||
any = 0;
|
any = 0;
|
||||||
for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
|
for (i = 0; i < mp->ma_size; i++) {
|
||||||
if (ep->me_value != NULL) {
|
dictentry *ep = mp->ma_table + i;
|
||||||
|
PyObject *pvalue = ep->me_value;
|
||||||
|
if (pvalue != NULL) {
|
||||||
|
/* Prevent PyObject_Repr from deleting value during
|
||||||
|
key format */
|
||||||
|
Py_INCREF(pvalue);
|
||||||
if (any++ > 0)
|
if (any++ > 0)
|
||||||
fprintf(fp, ", ");
|
fprintf(fp, ", ");
|
||||||
if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) {
|
if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) {
|
||||||
|
Py_DECREF(pvalue);
|
||||||
Py_ReprLeave((PyObject*)mp);
|
Py_ReprLeave((PyObject*)mp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fprintf(fp, ": ");
|
fprintf(fp, ": ");
|
||||||
if (PyObject_Print(ep->me_value, fp, 0) != 0) {
|
if (PyObject_Print(ep->me_value, fp, 0) != 0) {
|
||||||
|
Py_DECREF(pvalue);
|
||||||
Py_ReprLeave((PyObject*)mp);
|
Py_ReprLeave((PyObject*)mp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Py_DECREF(pvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(fp, "}");
|
fprintf(fp, "}");
|
||||||
|
|
@ -779,7 +786,6 @@ dict_repr(dictobject *mp)
|
||||||
PyObject *sepa, *colon;
|
PyObject *sepa, *colon;
|
||||||
register int i;
|
register int i;
|
||||||
register int any;
|
register int any;
|
||||||
register dictentry *ep;
|
|
||||||
|
|
||||||
i = Py_ReprEnter((PyObject*)mp);
|
i = Py_ReprEnter((PyObject*)mp);
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
|
|
@ -792,13 +798,19 @@ dict_repr(dictobject *mp)
|
||||||
sepa = PyString_FromString(", ");
|
sepa = PyString_FromString(", ");
|
||||||
colon = PyString_FromString(": ");
|
colon = PyString_FromString(": ");
|
||||||
any = 0;
|
any = 0;
|
||||||
for (i = 0, ep = mp->ma_table; i < mp->ma_size && v; i++, ep++) {
|
for (i = 0; i < mp->ma_size && v; i++) {
|
||||||
if (ep->me_value != NULL) {
|
dictentry *ep = mp->ma_table + i;
|
||||||
|
PyObject *pvalue = ep->me_value;
|
||||||
|
if (pvalue != NULL) {
|
||||||
|
/* Prevent PyObject_Repr from deleting value during
|
||||||
|
key format */
|
||||||
|
Py_INCREF(pvalue);
|
||||||
if (any++)
|
if (any++)
|
||||||
PyString_Concat(&v, sepa);
|
PyString_Concat(&v, sepa);
|
||||||
PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_key));
|
PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_key));
|
||||||
PyString_Concat(&v, colon);
|
PyString_Concat(&v, colon);
|
||||||
PyString_ConcatAndDel(&v, PyObject_Repr(ep->me_value));
|
PyString_ConcatAndDel(&v, PyObject_Repr(pvalue));
|
||||||
|
Py_DECREF(pvalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PyString_ConcatAndDel(&v, PyString_FromString("}"));
|
PyString_ConcatAndDel(&v, PyString_FromString("}"));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue