Quality control, meet exceptions.c.

Fix a number of problems with the need for speed code:

One is doing this sort of thing:

    Py_DECREF(self->field);
    self->field = newval;
    Py_INCREF(self->field);

without being very sure that self->field doesn't start with a
value that has a __del__, because that almost certainly can lead
to segfaults.

As self->args is constrained to be an exact tuple we may as well
exploit this fact consistently.  This leads to quite a lot of
simplification (and, hey, probably better performance).

Add some error checking in places lacking it.

Fix some rather strange indentation in the Unicode code.

Delete some trailing whitespace.

More to come, I haven't fixed all the reference leaks yet...
This commit is contained in:
Michael W. Hudson 2006-05-28 15:51:40 +00:00
parent 80f8e80c15
commit 22a80e7cb0
1 changed files with 105 additions and 128 deletions

View File

@ -53,7 +53,7 @@ BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
Py_INCREF(self->args);
if (PyTuple_GET_SIZE(self->args) == 1) {
Py_DECREF(self->message);
Py_CLEAR(self->message);
self->message = PyTuple_GET_ITEM(self->args, 0);
Py_INCREF(self->message);
}
@ -79,7 +79,6 @@ BaseException_dealloc(PyBaseExceptionObject *self)
int
BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg)
{
if (self->dict)
Py_VISIT(self->dict);
Py_VISIT(self->args);
Py_VISIT(self->message);
@ -91,24 +90,13 @@ BaseException_str(PyBaseExceptionObject *self)
{
PyObject *out;
switch (PySequence_Length(self->args)) {
switch (PyTuple_GET_SIZE(self->args)) {
case 0:
out = PyString_FromString("");
break;
case 1:
{
PyObject *tmp = PySequence_GetItem(self->args, 0);
if (tmp) {
out = PyObject_Str(tmp);
Py_DECREF(tmp);
}
else
out = NULL;
out = PyObject_Str(PyTuple_GET_ITEM(self->args, 0));
break;
}
case -1:
PyErr_Clear();
/* Fall through */
default:
out = PyObject_Str(self->args);
break;
@ -120,28 +108,14 @@ BaseException_str(PyBaseExceptionObject *self)
static PyObject *
BaseException_repr(PyBaseExceptionObject *self)
{
Py_ssize_t args_len;
PyObject *repr_suffix;
PyObject *repr;
char *name;
char *dot;
args_len = PySequence_Length(self->args);
if (args_len < 0) {
return NULL;
}
if (args_len == 0) {
repr_suffix = PyString_FromString("()");
repr_suffix = PyObject_Repr(self->args);
if (!repr_suffix)
return NULL;
}
else {
PyObject *args_repr = PyObject_Repr(self->args);
if (!args_repr)
return NULL;
repr_suffix = args_repr;
}
name = (char *)self->ob_type->tp_name;
dot = strrchr(name, '.');
@ -172,18 +146,10 @@ BaseException_reduce(PyBaseExceptionObject *self)
static PyObject *
BaseException_unicode(PyBaseExceptionObject *self)
{
if (PySequence_Length(self->args) == 0)
if (PyTuple_GET_SIZE(self->args) == 0)
return PyUnicode_FromUnicode(NULL, 0);
if (PySequence_Length(self->args) == 1) {
PyObject *temp = PySequence_GetItem(self->args, 0);
PyObject *unicode_obj;
if (!temp) {
return NULL;
}
unicode_obj = PyObject_Unicode(temp);
Py_DECREF(temp);
return unicode_obj;
}
if (PyTuple_GET_SIZE(self->args) == 1)
return PyObject_Unicode(PyTuple_GET_ITEM(self->args, 0));
return PyObject_Unicode(self->args);
}
#endif /* Py_USING_UNICODE */
@ -445,7 +411,9 @@ SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds)
if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
return -1;
Py_DECREF(self->code);
if (size == 0)
return 0;
Py_CLEAR(self->code);
if (size == 1)
self->code = PyTuple_GET_ITEM(args, 0);
else if (size > 1)
@ -514,12 +482,9 @@ EnvironmentError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!self)
return NULL;
self->myerrno = Py_None;
Py_INCREF(Py_None);
self->strerror = Py_None;
Py_INCREF(Py_None);
self->filename = Py_None;
Py_INCREF(Py_None);
MAKE_IT_NONE(self->myerrno);
MAKE_IT_NONE(self->strerror);
MAKE_IT_NONE(self->filename);
return (PyObject *)self;
}
@ -553,17 +518,17 @@ EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args,
&myerrno, &strerror, &filename)) {
return -1;
}
Py_DECREF(self->myerrno); /* replacing */
Py_CLEAR(self->myerrno); /* replacing */
self->myerrno = myerrno;
Py_INCREF(self->myerrno);
Py_DECREF(self->strerror); /* replacing */
Py_CLEAR(self->strerror); /* replacing */
self->strerror = strerror;
Py_INCREF(self->strerror);
/* self->filename will remain Py_None otherwise */
if (filename != NULL) {
Py_DECREF(self->filename); /* replacing */
Py_CLEAR(self->filename); /* replacing */
self->filename = filename;
Py_INCREF(self->filename);
@ -606,6 +571,9 @@ EnvironmentError_traverse(PyEnvironmentErrorObject *self, visitproc visit,
static PyObject *
EnvironmentError_str(PyEnvironmentErrorObject *self)
{
/* XXX this needs to be rewritten to cope with any of self->filename,
self->strerror and self->myerrno being NULL.
*/
PyObject *rtnval = NULL;
if (self->filename != Py_None) {
@ -677,20 +645,17 @@ EnvironmentError_reduce(PyEnvironmentErrorObject *self)
PyObject *res = NULL, *tmp;
/* self->args is only the first two real arguments if there was a
* file name given to EnvironmentError. */
if (PyTuple_Check(args) &&
PyTuple_GET_SIZE(args) == 2 &&
if (PyTuple_GET_SIZE(args) == 2 &&
self->filename != Py_None) {
args = PyTuple_New(3);
if (!args) return NULL;
tmp = PyTuple_GetItem(self->args, 0);
if (!tmp) goto finish;
tmp = PyTuple_GET_ITEM(self->args, 0);
Py_INCREF(tmp);
PyTuple_SET_ITEM(args, 0, tmp);
tmp = PyTuple_GetItem(self->args, 1);
if (!tmp) goto finish;
tmp = PyTuple_GET_ITEM(self->args, 1);
Py_INCREF(tmp);
PyTuple_SET_ITEM(args, 1, tmp);
@ -700,7 +665,6 @@ EnvironmentError_reduce(PyEnvironmentErrorObject *self)
Py_INCREF(args);
}
res = PyTuple_Pack(3, self->ob_type, args, self->dict);
finish:
Py_DECREF(args);
return res;
}
@ -783,6 +747,9 @@ WindowsError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *)self;
}
/* XXX this is dead code, surely? EnvironmentError_new always sets
self->myerrno to None! */
/* Set errno to the POSIX errno, and winerror to the Win32
error code. */
errcode = PyInt_AsLong(self->myerrno);
@ -850,6 +817,8 @@ WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds)
static PyObject *
WindowsError_str(PyWindowsErrorObject *self)
{
/* XXX this probably also needs to be rewritten to cope with NULL-ness of
the fields */
PyObject *repr = NULL;
PyObject *fmt = NULL;
PyObject *tuple = NULL;
@ -995,7 +964,7 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
return -1;
if (lenargs >= 1) {
Py_DECREF(self->msg);
Py_CLEAR(self->msg);
self->msg = PyTuple_GET_ITEM(args, 0);
Py_INCREF(self->msg);
}
@ -1004,21 +973,30 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
info = PySequence_Tuple(info);
if (!info) return -1;
Py_DECREF(self->filename);
if (PyTuple_GET_SIZE(info) != 4) {
/* not a very good error message, but it's what Python 2.4 gives */
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
Py_DECREF(info);
return -1;
}
Py_CLEAR(self->filename);
self->filename = PyTuple_GET_ITEM(info, 0);
Py_INCREF(self->filename);
Py_DECREF(self->lineno);
Py_CLEAR(self->lineno);
self->lineno = PyTuple_GET_ITEM(info, 1);
Py_INCREF(self->lineno);
Py_DECREF(self->offset);
Py_CLEAR(self->offset);
self->offset = PyTuple_GET_ITEM(info, 2);
Py_INCREF(self->offset);
Py_DECREF(self->text);
Py_CLEAR(self->text);
self->text = PyTuple_GET_ITEM(info, 3);
Py_INCREF(self->text);
Py_DECREF(info);
}
return 0;
}
@ -1196,9 +1174,8 @@ KeyError_str(PyBaseExceptionObject *self)
string, that string will be displayed in quotes. Too bad.
If args is anything else, use the default BaseException__str__().
*/
if (PyTuple_Check(self->args) && PyTuple_GET_SIZE(self->args) == 1) {
PyObject *key = PyTuple_GET_ITEM(self->args, 0);
return PyObject_Repr(key);
if (PyTuple_GET_SIZE(self->args) == 1) {
return PyObject_Repr(PyTuple_GET_ITEM(self->args, 0));
}
return BaseException_str(self);
}