Type checking inside a C extension... doesn't throw exception on failure

Stephen Horne steve at ninereeds.fsnet.co.uk
Tue Apr 6 10:34:34 EDT 2004


On Tue, 06 Apr 2004 11:54:30 +0800, Jon Perez <jbperez808 at yahoo.com>
wrote:

>Paul Prescod wrote:
>
>> It isn't true that PyLong_AsLong does no type checking. It does. It 
>> reports problems through the standard Python exception system.
>
>This illustrates a case where a crash occurs instead of an
>exception being thrown.  Feed spam.getstring() something besides a
>string:
>
>static PyObject *spam_getstring(PyObject *self, PyObject *args) {
>   PyObject *tup, *a, *b;
>
>   char strstr[100];
>
>   if (!PyArg_ParseTuple(args, "O", &strobj))
>     return NULL;
>
>   // PyString_AsString(strobj);  // raises exception
>   strcpy(strstr,PyString_AsString(strobj));  /* crashes!! */
>
>   Py_INCREF(Py_None);
>   return Py_None;
>}
>
>What gives? Shouldn't the exception be raised within PyString_AsString()
>before it even gets a chance to return a value to strcpy()?

I assume you're talking about when the PyString_AsString *isn't*
commented out ;-)


Python exceptions aren't converted to C exceptions, and the Python C
API doesn't use C exceptions at all. There is a good reason for this.
C doesn't have exceptions - C++ does, but this is a C API.

Given that C lacks exceptions, there is no practical (and portable)
way to forcibly unwind the stack. Even if something could be done with
longjump, for instance, there would be the issue of how your function
gets to do its cleanup.

Therefore, the simplest way for a Python C API function to propogate a
Python exception is by returning an error return value to the caller,
and keeping associated data in global variables. The caller then takes
on the responsibility for propogating the exception up to its caller
and so on. Which is precisely what Python appears to do. The caller
needs to check for the error value, do any neccessary cleanup, and
then propogate the error out of the function.

Python C API functions often return zero for error IIRC, so...

  if (PyString_AsString(strobj) == 0)  {  return 0;  }

Should ensure that the Python exception raised by PyString_AsString is
propogated correctly.


-- 
Steve Horne

steve at ninereeds dot fsnet dot co dot uk



More information about the Python-list mailing list