[Zope3-dev] Potential bug of intid

Tadashi Matsumoto ma2 at city.plala.jp
Sun Dec 11 04:23:08 EST 2005


Hello

I was looking into the following code of intid's __init__.py.


     91     def _generateId(self):
     92         """Generate an id which is not yet taken.
     93 
     94         This tries to allocate sequential ids so they fall into the
     95         same BTree bucket, and randomizes if it stumbles upon a
     96         used one.
     97         """
     98         while True:
     99             if self._v_nextid is None:
    100                 self._v_nextid = random.randint(0, 2**31)
    101             uid = self._v_nextid
    102             self._v_nextid += 1
    103             if uid not in self.refs:
    104                 return uid
    105             self._v_nextid = None
    106 
    107     def register(self, ob):
    108         # Note that we'll still need to keep this proxy removal.
    109         ob = removeSecurityProxy(ob)
    110         key = IKeyReference(ob)
    111 
    112         if key in self.ids:
    113             return self.ids[key]
    114         uid = self._generateId()
    115         self.refs[uid] = key
    116         self.ids[key] = uid
    117         return uid
    118 


2**31 used at the line 100 is a long integer, and there is a possibility
of generating long integer. long interger can not be used with Btree
module.

In fact,

>>> from BTrees import IOBTree
>>> t=IOBTree.IOBTree()
>>> t[2**30] = 'abc'
>>> t[2**31] = 'efg'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: expected integer key
>>>

I think it is better to use, for example, 2**30 instead of 2**31.

By the way, there is a probability (less than 1/2**31 percent) of
generating same intids, if thread switching occurs between the line
114 and 115.

----
Tadashi Matsumoto
ma2 at city.plala.jp


More information about the Zope3-dev mailing list