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