lookdict: stop more insane core-dump mutating comparison cases. Should
be possible to provoke unbounded recursion now, but leaving that to someone else to provoke and repair. Bugfix candidate -- although this is getting harder to backstitch, and the cases it's protecting against are mondo contrived.
This commit is contained in:
parent
7b5d0afb1e
commit
453163d842
@ -215,3 +215,71 @@ print >> f, str(dict)
|
|||||||
f.close()
|
f.close()
|
||||||
os.unlink(TESTFN)
|
os.unlink(TESTFN)
|
||||||
del f, dict
|
del f, dict
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# And another core-dumper from Michael Hudson.
|
||||||
|
|
||||||
|
dict = {}
|
||||||
|
|
||||||
|
# let's force dict to malloc its table
|
||||||
|
for i in range(1, 10):
|
||||||
|
dict[i] = i
|
||||||
|
|
||||||
|
class Machiavelli2:
|
||||||
|
def __eq__(self, other):
|
||||||
|
dict.clear()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
dict[Machiavelli2()] = Machiavelli2()
|
||||||
|
|
||||||
|
try:
|
||||||
|
dict[Machiavelli2()]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
del dict
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# And another core-dumper from Michael Hudson.
|
||||||
|
|
||||||
|
dict = {}
|
||||||
|
|
||||||
|
# let's force dict to malloc its table
|
||||||
|
for i in range(1, 10):
|
||||||
|
dict[i] = i
|
||||||
|
|
||||||
|
class Machiavelli3:
|
||||||
|
def __init__(self, id):
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if self.id == other.id:
|
||||||
|
dict.clear()
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%s(%s)"%(self.__class__.__name__, self.id)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
dict[Machiavelli3(1)] = Machiavelli3(0)
|
||||||
|
dict[Machiavelli3(2)] = Machiavelli3(0)
|
||||||
|
|
||||||
|
f = open(TESTFN, "w")
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
print >> f, dict[Machiavelli3(2)]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
os.unlink(TESTFN)
|
||||||
|
|
||||||
|
del dict
|
||||||
|
@ -255,6 +255,7 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
|
|||||||
register int checked_error;
|
register int checked_error;
|
||||||
register int cmp;
|
register int cmp;
|
||||||
PyObject *err_type, *err_value, *err_tb;
|
PyObject *err_type, *err_value, *err_tb;
|
||||||
|
PyObject *startkey;
|
||||||
|
|
||||||
i = hash & mask;
|
i = hash & mask;
|
||||||
ep = &ep0[i];
|
ep = &ep0[i];
|
||||||
@ -272,11 +273,23 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
|
|||||||
restore_error = 1;
|
restore_error = 1;
|
||||||
PyErr_Fetch(&err_type, &err_value, &err_tb);
|
PyErr_Fetch(&err_type, &err_value, &err_tb);
|
||||||
}
|
}
|
||||||
cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
|
startkey = ep->me_key;
|
||||||
if (cmp > 0)
|
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||||
goto Done;
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
if (ep0 == mp->ma_table && ep->me_key == startkey) {
|
||||||
|
if (cmp > 0)
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* The compare did major nasty stuff to the
|
||||||
|
* dict: start over.
|
||||||
|
* XXX A clever adversary could prevent this
|
||||||
|
* XXX from terminating.
|
||||||
|
*/
|
||||||
|
ep = lookdict(mp, key, hash);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
freeslot = NULL;
|
freeslot = NULL;
|
||||||
}
|
}
|
||||||
@ -302,11 +315,23 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
|
|||||||
&err_tb);
|
&err_tb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
|
startkey = ep->me_key;
|
||||||
if (cmp > 0)
|
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
|
||||||
break;
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
if (ep0 == mp->ma_table && ep->me_key == startkey) {
|
||||||
|
if (cmp > 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* The compare did major nasty stuff to the
|
||||||
|
* dict: start over.
|
||||||
|
* XXX A clever adversary could prevent this
|
||||||
|
* XXX from terminating.
|
||||||
|
*/
|
||||||
|
ep = lookdict(mp, key, hash);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (ep->me_key == dummy && freeslot == NULL)
|
else if (ep->me_key == dummy && freeslot == NULL)
|
||||||
freeslot = ep;
|
freeslot = ep;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user