Hi,

I tracked down an issue that was giving me segfaults with a poor __getbuffer__ implementation and modified the compiler to catch this case.

I couldn't figure out how to create an account on Trac, so instead of submitting a patch there, I'm just sending this email. Included is a testcase added to tests/run/bufaccess.pyx. This is a patch against cython-devel and I release this under the PSF license (like the rest of Cython).

I had to use "hg diff -b" to create this patch while ignoring whitespace because I have emacs configured to strip trailing whitespace, which caused lots of false positives on the code. So, hopefully, this patch will still apply cleanly.

(The patch also includes a tiny fix to the ErrorBuffer implementation in tests/run/bufaccess.pyx.)

-Andrew
diff -r 6488f2d89e72 Cython/Compiler/Buffer.py
--- a/Cython/Compiler/Buffer.py	Tue Aug 19 04:13:56 2008 -0700
+++ b/Cython/Compiler/Buffer.py	Wed Aug 20 10:59:34 2008 +0200
@@ -531,6 +531,10 @@ def get_getbuffer_code(dtype, code):
           }
           buf->buf = NULL;
           if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail;
+          if (buf->buf==NULL) {
+            __Pyx_BufferCreationError(buf);
+            goto fail;
+          }
           if (buf->ndim != nd) {
             __Pyx_BufferNdimError(buf, nd);
             goto fail;
@@ -660,6 +664,7 @@ static INLINE const char* __Pyx_ConsumeW
 static INLINE const char* __Pyx_ConsumeWhitespace(const char* ts); /*proto*/
 static INLINE const char* __Pyx_BufferTypestringCheckEndian(const char* ts); /*proto*/
 static void __Pyx_BufferNdimError(Py_buffer* buffer, int expected_ndim); /*proto*/
+static void __Pyx_BufferCreationError(Py_buffer* buffer); /*proto*/
 """, """
 static INLINE void __Pyx_SafeReleaseBuffer(PyObject* obj, Py_buffer* info) {
   if (info->buf == NULL) return;
@@ -718,6 +723,11 @@ static void __Pyx_BufferNdimError(Py_buf
                expected_ndim, buffer->ndim);
 }
 
+static void __Pyx_BufferCreationError(Py_buffer* buffer) {
+  PyErr_Format(PyExc_RuntimeError,
+               "Expected buffer to be created, but none was.");
+}
+
 """]
 
 raise_buffer_fallback_code = ["""
diff -r 6488f2d89e72 tests/run/bufaccess.pyx
--- a/tests/run/bufaccess.pyx	Tue Aug 19 04:13:56 2008 -0700
+++ b/tests/run/bufaccess.pyx	Wed Aug 20 10:59:34 2008 +0200
@@ -214,6 +214,20 @@ def acquire_nonbuffer2():
     except Exception:
         print buf[0], buf[3]
 
[EMAIL PROTECTED]
+def deal_with_bad_buffer_implementation():
+    """
+    >>> deal_with_bad_buffer_implementation()
+    bad buffer implementation detected
+    """
+    cdef object[int] buf
+    try:
+        buf = BadBufferImplementation("working")
+    except RuntimeError, err:
+        if err.args[0] == "Expected buffer to be created, but none was.":
+            print "bad buffer implementation detected"
+        else:
+            raise
 
 @testcase
 def as_argument(object[int] bufarg, int n):
@@ -1052,11 +1066,21 @@ cdef class ErrorBuffer:
     def __init__(self, label):
         self.label = label
 
-    def __getbuffer__(MockBuffer self, Py_buffer* buffer, int flags):
+    def __getbuffer__(ErrorBuffer self, Py_buffer* buffer, int flags):
         raise Exception("acquiring %s" % self.label)
 
-    def __releasebuffer__(MockBuffer self, Py_buffer* buffer):
+    def __releasebuffer__(ErrorBuffer self, Py_buffer* buffer):
         raise Exception("releasing %s" % self.label)
+
+cdef class BadBufferImplementation:
+    cdef object label
+
+    def __init__(self, label):
+        self.label = label
+
+    def __getbuffer__(BadBufferImplementation self,
+                      Py_buffer* buffer, int flags):
+        pass
 
 #
 # Typed buffers
@@ -1107,5 +1131,5 @@ def bufdefaults1(IntStridedMockBuffer[in
     ['FORMAT', 'ND', 'STRIDES']
     """
     pass
-    
 
+
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to