]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
lookdict: stop more insane core-dump mutating comparison cases. Should
authorTim Peters <tim.peters@gmail.com>
Sun, 3 Jun 2001 04:54:32 +0000 (04:54 +0000)
committerTim Peters <tim.peters@gmail.com>
Sun, 3 Jun 2001 04:54:32 +0000 (04:54 +0000)
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.

Lib/test/test_mutants.py
Objects/dictobject.c

index 88a3a02a5e8f6561f4af4c4fac0b6b8b23d32bb4..9ee1bb7537db090f419efb941c25ef70fdda7a09 100644 (file)
@@ -215,3 +215,71 @@ print >> f, str(dict)
 f.close()
 os.unlink(TESTFN)
 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
index 69fe67e867813cf6cc12acb00596e20ece496182..ce44abef23377658d944b2202688985386200a59 100644 (file)
@@ -255,6 +255,7 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
        register int checked_error;
        register int cmp;
        PyObject *err_type, *err_value, *err_tb;
+       PyObject *startkey;
 
        i = hash & mask;
        ep = &ep0[i];
@@ -272,11 +273,23 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
                                restore_error = 1;
                                PyErr_Fetch(&err_type, &err_value, &err_tb);
                        }
-                       cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
-                       if (cmp > 0)
-                               goto Done;
+                       startkey = ep->me_key;
+                       cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
                        if (cmp < 0)
                                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;
        }
@@ -302,11 +315,23 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
                                                    &err_tb);
                                }
                        }
-                       cmp = PyObject_RichCompareBool(ep->me_key, key, Py_EQ);
-                       if (cmp > 0)
-                               break;
+                       startkey = ep->me_key;
+                       cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
                        if (cmp < 0)
                                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)
                        freeslot = ep;