[Zodb-checkins] SVN: ZODB/trunk/src/ Bug Fixed

Jim Fulton jim at zope.com
Tue Oct 26 17:14:00 EDT 2010


Log message for revision 117933:
  Bug Fixed
  - BTrees allowed object keys with insane comparison. (Comparison
    inherited from object, which compares based on in-process address.)
    Now BTrees raise TypeError is an attempt is made to save a key with
    comparison inherited from object. (This doesn't apply to old-style
    class instances.)
  

Changed:
  U   ZODB/trunk/src/BTrees/BTreeModuleTemplate.c
  U   ZODB/trunk/src/BTrees/objectkeymacros.h
  U   ZODB/trunk/src/BTrees/tests/testBTrees.py
  U   ZODB/trunk/src/CHANGES.txt
  U   ZODB/trunk/src/ZODB/ConflictResolution.txt

-=-
Modified: ZODB/trunk/src/BTrees/BTreeModuleTemplate.c
===================================================================
--- ZODB/trunk/src/BTrees/BTreeModuleTemplate.c	2010-10-26 20:29:33 UTC (rev 117932)
+++ ZODB/trunk/src/BTrees/BTreeModuleTemplate.c	2010-10-26 21:14:00 UTC (rev 117933)
@@ -465,6 +465,12 @@
 {
     PyObject *m, *d, *c;
 
+#ifdef KEY_TYPE_IS_PYOBJECT
+    object_ = PyTuple_GetItem(Py_None->ob_type->tp_bases, 0);
+    if (object_ == NULL)
+      return;
+#endif
+
     sort_str = PyString_InternFromString("sort");
     if (!sort_str)
 	return;

Modified: ZODB/trunk/src/BTrees/objectkeymacros.h
===================================================================
--- ZODB/trunk/src/BTrees/objectkeymacros.h	2010-10-26 20:29:33 UTC (rev 117932)
+++ ZODB/trunk/src/BTrees/objectkeymacros.h	2010-10-26 21:14:00 UTC (rev 117933)
@@ -1,9 +1,31 @@
 #define KEYMACROS_H "$Id$\n"
 #define KEY_TYPE PyObject *
 #define KEY_TYPE_IS_PYOBJECT
+
+#include "Python.h"
+
+static PyObject *object_;
+
+static int
+check_argument_cmp(PyObject *arg)
+{
+  if (arg->ob_type->tp_richcompare == NULL
+      &&
+      arg->ob_type->tp_compare ==
+      ((PyTypeObject *)object_)->ob_type->tp_compare
+      )
+    {
+      PyErr_SetString(PyExc_TypeError, "Object has default comparison");
+      return 0;
+    }
+  return 1;
+}
+
 #define TEST_KEY_SET_OR(V, KEY, TARGET) if ( ( (V) = PyObject_Compare((KEY),(TARGET)) ), PyErr_Occurred() )
 #define INCREF_KEY(k) Py_INCREF(k)
 #define DECREF_KEY(KEY) Py_DECREF(KEY)
 #define COPY_KEY(KEY, E) KEY=(E)
 #define COPY_KEY_TO_OBJECT(O, K) O=(K); Py_INCREF(O)
-#define COPY_KEY_FROM_ARG(TARGET, ARG, S) TARGET=(ARG)
+#define COPY_KEY_FROM_ARG(TARGET, ARG, S) \
+    TARGET=(ARG); \
+    (S) = check_argument_cmp(ARG); 

Modified: ZODB/trunk/src/BTrees/tests/testBTrees.py
===================================================================
--- ZODB/trunk/src/BTrees/tests/testBTrees.py	2010-10-26 20:29:33 UTC (rev 117932)
+++ ZODB/trunk/src/BTrees/tests/testBTrees.py	2010-10-26 21:14:00 UTC (rev 117933)
@@ -1884,6 +1884,39 @@
     def setUp(self):
         self.t = OOBTree()
 
+    def testRejectDefaultComparison(self):
+        # Check that passing int keys w default comparison fails.
+        # Only applies to new-style class instances. Old-style
+        # instances are too hard to introspect.
+
+        # This is white box because we know that the check is being
+        # used in a function that's used in lots of places.
+        # Otherwise, there are many permutations that would have to be
+        # checked.
+
+        class C(object):
+            pass
+
+        self.assertRaises(TypeError, lambda : self.t.__setitem__(C(), 1))
+
+        class C(object):
+            def __cmp__(*args):
+                return 1
+
+        c = C()
+        self.t[c] = 1
+
+        self.t.clear()
+
+        class C(object):
+            def __lt__(*args):
+                return 1
+
+        c = C()
+        self.t[c] = 1
+
+        self.t.clear()
+
 if using64bits:
     class IIBTreeTest(BTreeTests, TestLongIntKeys, TestLongIntValues):
         def setUp(self):
@@ -1922,9 +1955,6 @@
         self.t = OLBTree()
     def getTwoKeys(self):
         return object(), object()
-class OOBTreeTest(BTreeTests):
-    def setUp(self):
-        self.t = OOBTree()
 
 
 # cmp error propagation tests

Modified: ZODB/trunk/src/CHANGES.txt
===================================================================
--- ZODB/trunk/src/CHANGES.txt	2010-10-26 20:29:33 UTC (rev 117932)
+++ ZODB/trunk/src/CHANGES.txt	2010-10-26 21:14:00 UTC (rev 117933)
@@ -2,6 +2,18 @@
  Change History
 ================
 
+3.11.0 (2010-??-??)
+===================
+
+Bugs Fixed
+----------
+
+- BTrees allowed object keys with insane comparison. (Comparison
+  inherited from object, which compares based on in-process address.)
+  Now BTrees raise TypeError is an attempt is made to save a key with
+  comparison inherited from object. (This doesn't apply to old-style
+  class instances.)
+
 3.10.1 (2010-10-??)
 ===================
 

Modified: ZODB/trunk/src/ZODB/ConflictResolution.txt
===================================================================
--- ZODB/trunk/src/ZODB/ConflictResolution.txt	2010-10-26 20:29:33 UTC (rev 117932)
+++ ZODB/trunk/src/ZODB/ConflictResolution.txt	2010-10-26 21:14:00 UTC (rev 117933)
@@ -65,6 +65,11 @@
             from persistent import Persistent
             class PCounter(Persistent):
                 '`value` is readonly; increment it with `inc`.'
+
+                def __cmp__(self, other):
+                    'Fool BTree checks for sane comparison :/'
+                    return object.__cmp__(self, other)
+
                 _val = 0
                 def inc(self):
                     self._val += 1



More information about the Zodb-checkins mailing list