diff Objects/dictobject.c @ 18023:8d2bbbbf2cb9 legacy-trunk

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.
author Tim Peters <tim.peters@gmail.com>
date Sun, 03 Jun 2001 04:54:32 +0000
parents bd1c4fe977cb
children b99979d0f9e7
line wrap: on
line diff
--- a/Objects/dictobject.c	Sun Jun 03 04:14:43 2001 +0000
+++ b/Objects/dictobject.c	Sun Jun 03 04:54:32 2001 +0000
@@ -255,6 +255,7 @@
 	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 @@
 				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 @@
 						    &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;