[Zodb-checkins] SVN: ZODB/branches/3.8/ Bugs Fixed:

Jim Fulton jim at zope.com
Mon Sep 20 16:17:10 EDT 2010


Log message for revision 116687:
  Bugs Fixed:
  
  - Passing keys or values outside the range of 32-bit ints on 64-bit
    platforms led to undetected overflow errors. Now these cases cause
    Overflow errors to be raised.
  
  https://bugs.launchpad.net/zodb/+bug/143237
  

Changed:
  U   ZODB/branches/3.8/NEWS.txt
  U   ZODB/branches/3.8/src/BTrees/intkeymacros.h
  U   ZODB/branches/3.8/src/BTrees/intvaluemacros.h
  U   ZODB/branches/3.8/src/BTrees/tests/testBTrees.py

-=-
Modified: ZODB/branches/3.8/NEWS.txt
===================================================================
--- ZODB/branches/3.8/NEWS.txt	2010-09-20 20:08:30 UTC (rev 116686)
+++ ZODB/branches/3.8/NEWS.txt	2010-09-20 20:17:10 UTC (rev 116687)
@@ -13,6 +13,12 @@
   update or to constructors, causing Python to exit under certain
   circumstances.
 
+- Passing keys or values outside the range of 32-bit ints on 64-bit
+  platforms led to undetected overflow errors. Now these cases cause
+  Overflow errors to be raised.
+
+  https://bugs.launchpad.net/zodb/+bug/143237
+
 - Fixed a serious bug that caused cache failures when run
   with Python optimization turned on.
 

Modified: ZODB/branches/3.8/src/BTrees/intkeymacros.h
===================================================================
--- ZODB/branches/3.8/src/BTrees/intkeymacros.h	2010-09-20 20:08:30 UTC (rev 116686)
+++ ZODB/branches/3.8/src/BTrees/intkeymacros.h	2010-09-20 20:17:10 UTC (rev 116687)
@@ -21,9 +21,16 @@
 #define KEY_TYPE int
 #define KEY_CHECK PyInt_Check
 #define COPY_KEY_TO_OBJECT(O, K) O=PyInt_FromLong(K)
-#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS) \
-  if (PyInt_Check(ARG)) TARGET=PyInt_AS_LONG(ARG); else { \
-      PyErr_SetString(PyExc_TypeError, "expected integer key"); \
+#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS)                    \
+  if (PyInt_Check(ARG)) {                                         \
+      long vcopy = PyInt_AS_LONG(ARG);                            \
+      if ((int)vcopy != vcopy) {                                  \
+        PyErr_SetObject(PyExc_OverflowError, ARG);                \
+        (STATUS)=0; (TARGET)=0;                                   \
+      }                                                           \
+      else TARGET = vcopy;                                        \
+  } else {                                                        \
+      PyErr_SetString(PyExc_TypeError, "expected integer key");   \
       (STATUS)=0; (TARGET)=0; }
 #endif
 

Modified: ZODB/branches/3.8/src/BTrees/intvaluemacros.h
===================================================================
--- ZODB/branches/3.8/src/BTrees/intvaluemacros.h	2010-09-20 20:08:30 UTC (rev 116686)
+++ ZODB/branches/3.8/src/BTrees/intvaluemacros.h	2010-09-20 20:17:10 UTC (rev 116687)
@@ -18,11 +18,20 @@
 #else
 #define VALUE_TYPE int
 #define VALUE_PARSE "i"
-#define COPY_VALUE_TO_OBJECT(O, K) O=PyInt_FromLong(K) 
-#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
-  if (PyInt_Check(ARG)) TARGET=PyInt_AsLong(ARG); else { \
-      PyErr_SetString(PyExc_TypeError, "expected integer value"); \
-      (STATUS)=0; (TARGET)=0; } 
+#define COPY_VALUE_TO_OBJECT(O, K) O=PyInt_FromLong(K)
+
+#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS)                  \
+  if (PyInt_Check(ARG)) {                                         \
+      long vcopy = PyInt_AS_LONG(ARG);                            \
+      if ((int)vcopy != vcopy) {                                  \
+        PyErr_SetObject(PyExc_OverflowError, ARG);                \
+        (STATUS)=0; (TARGET)=0;                                   \
+      }                                                           \
+      else TARGET = vcopy;                                        \
+  } else {                                                        \
+      PyErr_SetString(PyExc_TypeError, "expected integer key");   \
+      (STATUS)=0; (TARGET)=0; }
+
 #endif
 
 #undef VALUE_TYPE_IS_PYOBJECT

Modified: ZODB/branches/3.8/src/BTrees/tests/testBTrees.py
===================================================================
--- ZODB/branches/3.8/src/BTrees/tests/testBTrees.py	2010-09-20 20:08:30 UTC (rev 116686)
+++ ZODB/branches/3.8/src/BTrees/tests/testBTrees.py	2010-09-20 20:17:10 UTC (rev 116687)
@@ -1623,6 +1623,29 @@
 class IIBTreeTest(BTreeTests):
     def setUp(self):
         self.t = IIBTree()
+
+    def testIIBTreeOverflow(self):
+        good = set()
+        b = self.t
+
+        def trial(i):
+            i = int(i)
+            try:
+                b[i] = 0
+            except (OverflowError, TypeError), v:
+                self.assertRaises(v.__class__, b.__setitem__, 0, i)
+            else:
+                good.add(i)
+                b[0] = i
+                self.assertEqual(b[0], i)
+
+        for i in range((1<<31) - 3, (1<<31) + 3):
+            trial(i)
+            trial(-i)
+
+        del b[0]
+        self.assertEqual(sorted(good), sorted(b))
+
 class IFBTreeTest(BTreeTests):
     def setUp(self):
         self.t = IFBTree()
@@ -1752,14 +1775,9 @@
             self.assertRaises(TypeError, s.insert, big)
             self.assertRaises(TypeError, s.insert, BTrees.family32.minint - 1)
         else: # 64 bit Python
-            s.insert(BTrees.family32.maxint + 1)
-            self.assert_(BTrees.family32.maxint + 1 not in list(s))
-            # yeah, it's len of 1 now, and rolled over to the minint...
-            # don't look...don't look...
-            s = IOTreeSet()
-            s.insert(BTrees.family32.minint - 1)
-            self.assert_(BTrees.family32.minint - 1 not in list(s))
-            # similarly, this is a len of 1, rolling over to the maxint...
+            self.assertRaises(OverflowError, s.insert, big)
+            self.assertRaises(OverflowError, s.insert,
+                              BTrees.family32.minint - 1)
         self.check_pickling(BTrees.family32)
 
     def test64(self):



More information about the Zodb-checkins mailing list