[pypy-svn] r79563 - pypy/branch/fast-forward/lib_pypy/_ctypes

afa at codespeak.net afa at codespeak.net
Fri Nov 26 16:31:07 CET 2010


Author: afa
Date: Fri Nov 26 16:31:05 2010
New Revision: 79563

Modified:
   pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py
   pypy/branch/fast-forward/lib_pypy/_ctypes/builtin.py
   pypy/branch/fast-forward/lib_pypy/_ctypes/pointer.py
Log:
Another common potential crasher:
cast() should keep the original object alive, and make a copy of its keepalives.

Remove _CData_value() this is a dangerous function when the value is a string:
the buffer may be freed as soon as the function returns!


Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_ctypes/basics.py	Fri Nov 26 16:31:05 2010
@@ -46,12 +46,6 @@
         else:
             return self.from_param(as_parameter)
 
-    def _CData_value(self, value):
-        cobj = self.from_param(value)
-        # we don't care here if this stuff will live afterwards, as we're
-        # interested only in value anyway
-        return cobj._get_buffer_value()
-
     def _CData_output(self, resbuffer, base=None, index=-1):
         #assert isinstance(resbuffer, _rawffi.ArrayInstance)
         """Used when data exits ctypes and goes into user code.

Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/builtin.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_ctypes/builtin.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_ctypes/builtin.py	Fri Nov 26 16:31:05 2010
@@ -11,7 +11,8 @@
 def _string_at_addr(addr, lgt):
     # address here can be almost anything
     import ctypes
-    arg = ctypes.c_void_p._CData_value(addr)
+    cobj = ctypes.c_void_p.from_param(addr)
+    arg = cobj._get_buffer_value()
     return _rawffi.charp2rawstring(arg, lgt)
 
 def set_conversion_mode(encoding, errors):
@@ -22,5 +23,6 @@
 
 def _wstring_at_addr(addr, lgt):
     import ctypes
-    arg = ctypes.c_void_p._CData_value(addr)
+    cobj = ctypes.c_void_p.from_param(addr)
+    arg = cobj._get_buffer_value()
     return _rawffi.wcharp2rawunicode(arg, lgt)

Modified: pypy/branch/fast-forward/lib_pypy/_ctypes/pointer.py
==============================================================================
--- pypy/branch/fast-forward/lib_pypy/_ctypes/pointer.py	(original)
+++ pypy/branch/fast-forward/lib_pypy/_ctypes/pointer.py	Fri Nov 26 16:31:05 2010
@@ -1,7 +1,8 @@
 
 import _rawffi
 from _ctypes.basics import _CData, _CDataMeta, cdata_from_address
-from _ctypes.basics import sizeof, byref, keepalive_key
+from _ctypes.basics import keepalive_key, store_reference, ensure_objects
+from _ctypes.basics import sizeof, byref
 from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
      array_slice_setitem
 
@@ -102,7 +103,10 @@
         return self._type_._CData_output(self._subarray(index), self, index)
 
     def __setitem__(self, index, value):
-        self._subarray(index)[0] = self._type_._CData_value(value)
+        cobj = self._type_.from_param(value)
+        if ensure_objects(cobj) is not None:
+            store_reference(self, index, cobj._objects)
+        self._subarray(index)[0] = cobj._get_buffer_value()
 
     def __nonzero__(self):
         return self._buffer[0] != 0
@@ -113,31 +117,34 @@
     if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
         raise TypeError("cast() argument 2 must be a pointer type, not %s"
                         % (tp,))
-    if isinstance(obj, Array):
-        ptr = tp.__new__(tp)
-        ptr._buffer = tp._ffiarray(1, autofree=True)
-        ptr._buffer[0] = obj._buffer
-        return ptr
     if isinstance(obj, (int, long)):
         result = tp()
         result._buffer[0] = obj
         return result
-    if obj is None:
+    elif obj is None:
         result = tp()
         return result
-    if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
+    elif isinstance(obj, Array):
+        ptr = tp.__new__(tp)
+        ptr._buffer = tp._ffiarray(1, autofree=True)
+        ptr._buffer[0] = obj._buffer
+        result = ptr
+    elif not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
         raise TypeError("cast() argument 1 must be a pointer, not %s"
                         % (type(obj),))
-    result = tp()
+    else:
+        result = tp()
+        result._buffer[0] = obj._buffer[0]
 
     # The casted objects '_objects' member:
-    # It must certainly contain the source objects one.
+    # From now on, both objects will use the same dictionary
+    # It must certainly contain the source objects
     # It must contain the source object itself.
     if obj._ensure_objects() is not None:
-        result._objects = {keepalive_key(0): obj._objects,
-                           keepalive_key(1): obj}
+        result._objects = obj._objects
+        if isinstance(obj._objects, dict):
+            result._objects[id(obj)] =  obj
 
-    result._buffer[0] = obj._buffer[0]
     return result
 
 def POINTER(cls):



More information about the Pypy-commit mailing list