diff options
Diffstat (limited to 'Objects/exceptions.c')
-rw-r--r-- | Objects/exceptions.c | 746 |
1 files changed, 356 insertions, 390 deletions
diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 6271372..3b79307 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1,3 +1,9 @@ +/* + * New exceptions.c written in Iceland by Richard Jones and Georg Brandl. + * + * Thanks go to Tim Peters and Michael Hudson for debugging. + */ + #define PY_SSIZE_T_CLEAN #include <Python.h> #include "structmember.h" @@ -36,7 +42,7 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - self->message = PyString_FromString(""); + self->message = PyString_FromString(""); if (!self->message) { Py_DECREF(self); return NULL; @@ -48,19 +54,22 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static int BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds) { + if (!_PyArg_NoKeywords(self->ob_type->tp_name, kwds)) + return -1; + Py_DECREF(self->args); self->args = args; 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); + Py_INCREF(self->message); } return 0; } -int +static int BaseException_clear(PyBaseExceptionObject *self) { Py_CLEAR(self->dict); @@ -76,11 +85,10 @@ BaseException_dealloc(PyBaseExceptionObject *self) self->ob_type->tp_free((PyObject *)self); } -int +static int BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg) { - if (self->dict) - Py_VISIT(self->dict); + Py_VISIT(self->dict); Py_VISIT(self->args); Py_VISIT(self->message); return 0; @@ -91,24 +99,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 +117,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) { + repr_suffix = PyObject_Repr(self->args); + if (!repr_suffix) return NULL; - } - - if (args_len == 0) { - repr_suffix = PyString_FromString("()"); - 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, '.'); @@ -161,9 +144,35 @@ BaseException_repr(PyBaseExceptionObject *self) static PyObject * BaseException_reduce(PyBaseExceptionObject *self) { - return PyTuple_Pack(3, self->ob_type, self->args, self->dict); + if (self->args && self->dict) + return PyTuple_Pack(3, self->ob_type, self->args, self->dict); + else + return PyTuple_Pack(2, self->ob_type, self->args); } +/* + * Needed for backward compatibility, since exceptions used to store + * all their attributes in the __dict__. Code is taken from cPickle's + * load_build function. + */ +static PyObject * +BaseException_setstate(PyObject *self, PyObject *state) +{ + PyObject *d_key, *d_value; + Py_ssize_t i = 0; + + if (state != Py_None) { + if (!PyDict_Check(state)) { + PyErr_SetString(PyExc_TypeError, "state is not a dictionary"); + return NULL; + } + while (PyDict_Next(state, &i, &d_key, &d_value)) { + if (PyObject_SetAttr(self, d_key, d_value) < 0) + return NULL; + } + } + Py_RETURN_NONE; +} #ifdef Py_USING_UNICODE /* while this method generates fairly uninspired output, it a least @@ -172,24 +181,17 @@ 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 */ static PyMethodDef BaseException_methods[] = { {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS }, + {"__setstate__", (PyCFunction)BaseException_setstate, METH_O }, #ifdef Py_USING_UNICODE {"__unicode__", (PyCFunction)BaseException_unicode, METH_NOARGS }, #endif @@ -274,6 +276,7 @@ BaseException_set_args(PyBaseExceptionObject *self, PyObject *val) } seq = PySequence_Tuple(val); if (!seq) return -1; + Py_CLEAR(self->args); self->args = seq; return 0; } @@ -356,13 +359,13 @@ static PyTypeObject _PyExc_ ## EXCNAME = { \ 0, \ EXC_MODULE_NAME # EXCNAME, \ sizeof(Py ## EXCSTORE ## Object), \ - 0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, \ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \ - PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \ - (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \ + PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \ + (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \ 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \ - (initproc)EXCSTORE ## _init, 0, EXCSTORE ## _new,\ + (initproc)EXCSTORE ## _init, 0, BaseException_new,\ }; \ PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME @@ -379,7 +382,7 @@ static PyTypeObject _PyExc_ ## EXCNAME = { \ (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \ EXCMEMBERS, 0, &_ ## EXCBASE, \ 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \ - (initproc)EXCSTORE ## _init, 0, EXCSTORE ## _new,\ + (initproc)EXCSTORE ## _init, 0, BaseException_new,\ }; \ PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME @@ -394,7 +397,7 @@ SimpleExtendsException(PyExc_BaseException, Exception, /* * StandardError extends Exception */ -SimpleExtendsException(PyExc_Exception, StandardError, +SimpleExtendsException(PyExc_Exception, StandardError, "Base class for all standard Python exceptions that do not represent\n" "interpreter exiting."); @@ -423,19 +426,6 @@ SimpleExtendsException(PyExc_Exception, GeneratorExit, /* * SystemExit extends BaseException */ -static PyObject * -SystemExit_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PySystemExitObject *self; - - self = (PySystemExitObject *)BaseException_new(type, args, kwds); - if (!self) - return NULL; - - MAKE_IT_NONE(self->code); - - return (PyObject *)self; -} static int SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds) @@ -445,7 +435,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) @@ -454,7 +446,7 @@ SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds) return 0; } -int +static int SystemExit_clear(PySystemExitObject *self) { Py_CLEAR(self->code); @@ -468,7 +460,7 @@ SystemExit_dealloc(PySystemExitObject *self) self->ob_type->tp_free((PyObject *)self); } -int +static int SystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg) { Py_VISIT(self->code); @@ -505,25 +497,6 @@ SimpleExtendsException(PyExc_StandardError, ImportError, * EnvironmentError extends StandardError */ -static PyObject * -EnvironmentError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyEnvironmentErrorObject *self = NULL; - - self = (PyEnvironmentErrorObject *)BaseException_new(type, args, 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); - - return (PyObject *)self; -} - /* Where a function has a single filename, such as open() or some * of the os module functions, PyErr_SetFromErrnoWithFilename() is * called, giving a third argument which is the filename. But, so @@ -548,22 +521,22 @@ EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args, if (PyTuple_GET_SIZE(args) <= 1) { return 0; } - - if (!PyArg_UnpackTuple(args, "EnvironmentError", 2, 3, + + if (!PyArg_UnpackTuple(args, "EnvironmentError", 2, 3, &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); @@ -577,7 +550,7 @@ EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args, return 0; } -int +static int EnvironmentError_clear(PyEnvironmentErrorObject *self) { Py_CLEAR(self->myerrno); @@ -593,7 +566,7 @@ EnvironmentError_dealloc(PyEnvironmentErrorObject *self) self->ob_type->tp_free((PyObject *)self); } -int +static int EnvironmentError_traverse(PyEnvironmentErrorObject *self, visitproc visit, void *arg) { @@ -608,22 +581,44 @@ EnvironmentError_str(PyEnvironmentErrorObject *self) { PyObject *rtnval = NULL; - if (self->filename != Py_None) { - PyObject *fmt = PyString_FromString("[Errno %s] %s: %s"); - PyObject *repr = PyObject_Repr(self->filename); - PyObject *tuple = PyTuple_New(3); + if (self->filename) { + PyObject *fmt; + PyObject *repr; + PyObject *tuple; - if (!fmt || !repr || !tuple) { - Py_XDECREF(fmt); - Py_XDECREF(repr); - Py_XDECREF(tuple); + fmt = PyString_FromString("[Errno %s] %s: %s"); + if (!fmt) + return NULL; + + repr = PyObject_Repr(self->filename); + if (!repr) { + Py_DECREF(fmt); return NULL; } - Py_INCREF(self->myerrno); - PyTuple_SET_ITEM(tuple, 0, self->myerrno); - Py_INCREF(self->strerror); - PyTuple_SET_ITEM(tuple, 1, self->strerror); - Py_INCREF(repr); + tuple = PyTuple_New(3); + if (!tuple) { + Py_DECREF(repr); + Py_DECREF(fmt); + return NULL; + } + + if (self->myerrno) { + Py_INCREF(self->myerrno); + PyTuple_SET_ITEM(tuple, 0, self->myerrno); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 0, Py_None); + } + if (self->strerror) { + Py_INCREF(self->strerror); + PyTuple_SET_ITEM(tuple, 1, self->strerror); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 1, Py_None); + } + PyTuple_SET_ITEM(tuple, 2, repr); rtnval = PyString_Format(fmt, tuple); @@ -631,20 +626,36 @@ EnvironmentError_str(PyEnvironmentErrorObject *self) Py_DECREF(fmt); Py_DECREF(tuple); } - else if (PyObject_IsTrue(self->myerrno) && - PyObject_IsTrue(self->strerror)) { - PyObject *fmt = PyString_FromString("[Errno %s] %s"); - PyObject *tuple = PyTuple_New(2); - - if (!fmt || !tuple) { - Py_XDECREF(fmt); - Py_XDECREF(tuple); + else if (self->myerrno && self->strerror) { + PyObject *fmt; + PyObject *tuple; + + fmt = PyString_FromString("[Errno %s] %s"); + if (!fmt) + return NULL; + + tuple = PyTuple_New(2); + if (!tuple) { + Py_DECREF(fmt); return NULL; } - Py_INCREF(self->myerrno); - PyTuple_SET_ITEM(tuple, 0, self->myerrno); - Py_INCREF(self->strerror); - PyTuple_SET_ITEM(tuple, 1, self->strerror); + + if (self->myerrno) { + Py_INCREF(self->myerrno); + PyTuple_SET_ITEM(tuple, 0, self->myerrno); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 0, Py_None); + } + if (self->strerror) { + Py_INCREF(self->strerror); + PyTuple_SET_ITEM(tuple, 1, self->strerror); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 1, Py_None); + } rtnval = PyString_Format(fmt, tuple); @@ -675,32 +686,30 @@ EnvironmentError_reduce(PyEnvironmentErrorObject *self) { PyObject *args = self->args; 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 && - self->filename != Py_None) { - + if (PyTuple_GET_SIZE(args) == 2 && self->filename) { 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); Py_INCREF(self->filename); PyTuple_SET_ITEM(args, 2, self->filename); - } else { + } else Py_INCREF(args); - } - res = PyTuple_Pack(3, self->ob_type, args, self->dict); - finish: + + if (self->dict) + res = PyTuple_Pack(3, self->ob_type, args, self->dict); + else + res = PyTuple_Pack(2, self->ob_type, args); Py_DECREF(args); return res; } @@ -714,14 +723,14 @@ static PyMethodDef EnvironmentError_methods[] = { ComplexExtendsException(PyExc_StandardError, EnvironmentError, EnvironmentError, EnvironmentError_dealloc, EnvironmentError_methods, EnvironmentError_members, - EnvironmentError_str, + EnvironmentError_str, "Base class for I/O related errors."); /* * IOError extends EnvironmentError */ -MiddlingExtendsException(PyExc_EnvironmentError, IOError, +MiddlingExtendsException(PyExc_EnvironmentError, IOError, EnvironmentError, "I/O operation failed."); @@ -738,7 +747,7 @@ MiddlingExtendsException(PyExc_EnvironmentError, OSError, #ifdef MS_WINDOWS #include "errmap.h" -int +static int WindowsError_clear(PyWindowsErrorObject *self) { Py_CLEAR(self->myerrno); @@ -755,7 +764,7 @@ WindowsError_dealloc(PyWindowsErrorObject *self) self->ob_type->tp_free((PyObject *)self); } -int +static int WindowsError_traverse(PyWindowsErrorObject *self, visitproc visit, void *arg) { Py_VISIT(self->myerrno); @@ -765,50 +774,6 @@ WindowsError_traverse(PyWindowsErrorObject *self, visitproc visit, void *arg) return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg); } -static PyObject * -WindowsError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *o_errcode = NULL; - long errcode; - PyWindowsErrorObject *self; - long posix_errno; - - self = (PyWindowsErrorObject *)EnvironmentError_new(type, args, kwds); - if (!self) - return NULL; - - if (self->myerrno == Py_None) { - self->winerror = self->myerrno; - Py_INCREF(self->winerror); - return (PyObject *)self; - } - - /* Set errno to the POSIX errno, and winerror to the Win32 - error code. */ - errcode = PyInt_AsLong(self->myerrno); - if (errcode == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - /* give a clearer error message */ - PyErr_SetString(PyExc_TypeError, "errno has to be an integer"); - goto failed; - } - posix_errno = winerror_to_errno(errcode); - - self->winerror = self->myerrno; - - o_errcode = PyInt_FromLong(posix_errno); - if (!o_errcode) - goto failed; - - self->myerrno = o_errcode; - - return (PyObject *)self; -failed: - /* Could not set errno. */ - Py_DECREF(self); - return NULL; -} - static int WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds) { @@ -820,12 +785,8 @@ WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds) == -1) return -1; - if (self->myerrno == Py_None) { - Py_DECREF(self->winerror); - self->winerror = self->myerrno; - Py_INCREF(self->winerror); + if (self->myerrno == NULL) return 0; - } /* Set errno to the POSIX errno, and winerror to the Win32 error code. */ @@ -834,7 +795,7 @@ WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds) return -1; posix_errno = winerror_to_errno(errcode); - Py_DECREF(self->winerror); + Py_CLEAR(self->winerror); self->winerror = self->myerrno; o_errcode = PyInt_FromLong(posix_errno); @@ -850,44 +811,93 @@ WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds) static PyObject * WindowsError_str(PyWindowsErrorObject *self) { - PyObject *repr = NULL; - PyObject *fmt = NULL; - PyObject *tuple = NULL; PyObject *rtnval = NULL; - if (self->filename != Py_None) { + if (self->filename) { + PyObject *fmt; + PyObject *repr; + PyObject *tuple; + fmt = PyString_FromString("[Error %s] %s: %s"); + if (!fmt) + return NULL; + repr = PyObject_Repr(self->filename); - if (!fmt || !repr) - goto finally; + if (!repr) { + Py_DECREF(fmt); + return NULL; + } + tuple = PyTuple_New(3); + if (!tuple) { + Py_DECREF(repr); + Py_DECREF(fmt); + return NULL; + } - tuple = PyTuple_Pack(3, self->myerrno, self->strerror, repr); - if (!tuple) - goto finally; + if (self->myerrno) { + Py_INCREF(self->myerrno); + PyTuple_SET_ITEM(tuple, 0, self->myerrno); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 0, Py_None); + } + if (self->strerror) { + Py_INCREF(self->strerror); + PyTuple_SET_ITEM(tuple, 1, self->strerror); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 1, Py_None); + } + + Py_INCREF(repr); + PyTuple_SET_ITEM(tuple, 2, repr); rtnval = PyString_Format(fmt, tuple); + + Py_DECREF(fmt); Py_DECREF(tuple); } - else if (PyObject_IsTrue(self->myerrno) && - PyObject_IsTrue(self->strerror)) { + else if (self->myerrno && self->strerror) { + PyObject *fmt; + PyObject *tuple; + fmt = PyString_FromString("[Error %s] %s"); if (!fmt) - goto finally; + return NULL; - tuple = PyTuple_Pack(2, self->myerrno, self->strerror); - if (!tuple) - goto finally; + tuple = PyTuple_New(2); + if (!tuple) { + Py_DECREF(fmt); + return NULL; + } + + if (self->myerrno) { + Py_INCREF(self->myerrno); + PyTuple_SET_ITEM(tuple, 0, self->myerrno); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 0, Py_None); + } + if (self->strerror) { + Py_INCREF(self->strerror); + PyTuple_SET_ITEM(tuple, 1, self->strerror); + } + else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(tuple, 1, Py_None); + } rtnval = PyString_Format(fmt, tuple); + + Py_DECREF(fmt); Py_DECREF(tuple); } else - rtnval = EnvironmentError_str((PyEnvironmentErrorObject *)self); + rtnval = EnvironmentError_str((PyEnvironmentErrorObject *)self); - finally: - Py_XDECREF(repr); - Py_XDECREF(fmt); - Py_XDECREF(tuple); return rtnval; } @@ -963,27 +973,6 @@ SimpleExtendsException(PyExc_StandardError, AttributeError, /* * SyntaxError extends StandardError */ -static PyObject * -SyntaxError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PySyntaxErrorObject *self = NULL; - - self = (PySyntaxErrorObject *)BaseException_new(type, args, kwds); - if (!self) - return NULL; - - MAKE_IT_NONE(self->msg) - MAKE_IT_NONE(self->filename) - MAKE_IT_NONE(self->lineno) - MAKE_IT_NONE(self->offset) - MAKE_IT_NONE(self->text) - - /* this is always None - yes, I know it doesn't seem to be used - anywhere, but it was in the previous implementation */ - MAKE_IT_NONE(self->print_file_and_line) - - return (PyObject *)self; -} static int SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds) @@ -995,7 +984,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,26 +993,35 @@ 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; } -int +static int SyntaxError_clear(PySyntaxErrorObject *self) { Py_CLEAR(self->msg); @@ -1042,7 +1040,7 @@ SyntaxError_dealloc(PySyntaxErrorObject *self) self->ob_type->tp_free((PyObject *)self); } -int +static int SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg) { Py_VISIT(self->msg); @@ -1079,53 +1077,58 @@ SyntaxError_str(PySyntaxErrorObject *self) { PyObject *str; PyObject *result; + int have_filename = 0; + int have_lineno = 0; + char *buffer = NULL; + Py_ssize_t bufsize; - str = PyObject_Str(self->msg); - result = str; + if (self->msg) + str = PyObject_Str(self->msg); + else + str = PyObject_Str(Py_None); + if (!str) return NULL; + /* Don't fiddle with non-string return (shouldn't happen anyway) */ + if (!PyString_Check(str)) return str; /* XXX -- do all the additional formatting with filename and lineno here */ - if (str != NULL && PyString_Check(str)) { - int have_filename = 0; - int have_lineno = 0; - char *buffer = NULL; - - have_filename = (self->filename != NULL) && - PyString_Check(self->filename); - have_lineno = (self->lineno != NULL) && PyInt_Check(self->lineno); - - if (have_filename || have_lineno) { - Py_ssize_t bufsize = PyString_GET_SIZE(str) + 64; - if (have_filename) - bufsize += PyString_GET_SIZE(self->filename); - - buffer = (char *)PyMem_MALLOC(bufsize); - if (buffer != NULL) { - if (have_filename && have_lineno) - PyOS_snprintf(buffer, bufsize, "%s (%s, line %ld)", - PyString_AS_STRING(str), - my_basename(PyString_AS_STRING(self->filename)), - PyInt_AsLong(self->lineno)); - else if (have_filename) - PyOS_snprintf(buffer, bufsize, "%s (%s)", - PyString_AS_STRING(str), - my_basename(PyString_AS_STRING(self->filename))); - else if (have_lineno) - PyOS_snprintf(buffer, bufsize, "%s (line %ld)", - PyString_AS_STRING(str), - PyInt_AsLong(self->lineno)); - - result = PyString_FromString(buffer); - PyMem_FREE(buffer); - - if (result == NULL) - result = str; - else - Py_DECREF(str); - } - } - } + have_filename = (self->filename != NULL) && + PyString_Check(self->filename); + have_lineno = (self->lineno != NULL) && PyInt_Check(self->lineno); + + if (!have_filename && !have_lineno) + return str; + + bufsize = PyString_GET_SIZE(str) + 64; + if (have_filename) + bufsize += PyString_GET_SIZE(self->filename); + + buffer = PyMem_MALLOC(bufsize); + if (buffer == NULL) + return str; + + if (have_filename && have_lineno) + PyOS_snprintf(buffer, bufsize, "%s (%s, line %ld)", + PyString_AS_STRING(str), + my_basename(PyString_AS_STRING(self->filename)), + PyInt_AsLong(self->lineno)); + else if (have_filename) + PyOS_snprintf(buffer, bufsize, "%s (%s)", + PyString_AS_STRING(str), + my_basename(PyString_AS_STRING(self->filename))); + else /* only have_lineno */ + PyOS_snprintf(buffer, bufsize, "%s (line %ld)", + PyString_AS_STRING(str), + PyInt_AsLong(self->lineno)); + + result = PyString_FromString(buffer); + PyMem_FREE(buffer); + + if (result == NULL) + result = str; + else + Py_DECREF(str); return result; } @@ -1196,9 +1199,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); } @@ -1248,7 +1250,7 @@ set_ssize_t(PyObject **attr, Py_ssize_t value) PyObject *obj = PyInt_FromSsize_t(value); if (!obj) return -1; - Py_XDECREF(*attr); + Py_CLEAR(*attr); *attr = obj; return 0; } @@ -1276,7 +1278,7 @@ set_string(PyObject **attr, const char *value) PyObject *obj = PyString_FromString(value); if (!obj) return -1; - Py_XDECREF(*attr); + Py_CLEAR(*attr); *attr = obj; return 0; } @@ -1342,6 +1344,7 @@ PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start) *start = 0; /*XXX check for values <0*/ if (*start>=size) *start = size-1; + Py_DECREF(obj); return 0; } return -1; @@ -1361,6 +1364,7 @@ PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start) *start = 0; if (*start>=size) *start = size-1; + Py_DECREF(obj); return 0; } return -1; @@ -1408,6 +1412,7 @@ PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end) *end = 1; if (*end>size) *end = size; + Py_DECREF(obj); return 0; } return -1; @@ -1427,6 +1432,7 @@ PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end) *end = 1; if (*end>size) *end = size; + Py_DECREF(obj); return 0; } return -1; @@ -1502,36 +1508,23 @@ PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason) } -static PyObject * -UnicodeError_new(PyTypeObject *type, PyObject *args, PyObject *kwds, - PyTypeObject *objecttype) -{ - PyUnicodeErrorObject *self; - - self = (PyUnicodeErrorObject *)BaseException_new(type, args, kwds); - if (!self) - return NULL; - - MAKE_IT_NONE(self->encoding); - MAKE_IT_NONE(self->object); - MAKE_IT_NONE(self->start); - MAKE_IT_NONE(self->end); - MAKE_IT_NONE(self->reason); - - return (PyObject *)self; -} - static int UnicodeError_init(PyUnicodeErrorObject *self, PyObject *args, PyObject *kwds, PyTypeObject *objecttype) { + Py_CLEAR(self->encoding); + Py_CLEAR(self->object); + Py_CLEAR(self->start); + Py_CLEAR(self->end); + Py_CLEAR(self->reason); + if (!PyArg_ParseTuple(args, "O!O!O!O!O!", &PyString_Type, &self->encoding, objecttype, &self->object, &PyInt_Type, &self->start, &PyInt_Type, &self->end, &PyString_Type, &self->reason)) { - self->encoding = self->object = self->start = self->end = + self->encoding = self->object = self->start = self->end = self->reason = NULL; return -1; } @@ -1545,7 +1538,7 @@ UnicodeError_init(PyUnicodeErrorObject *self, PyObject *args, PyObject *kwds, return 0; } -int +static int UnicodeError_clear(PyUnicodeErrorObject *self) { Py_CLEAR(self->encoding); @@ -1563,7 +1556,7 @@ UnicodeError_dealloc(PyUnicodeErrorObject *self) self->ob_type->tp_free((PyObject *)self); } -int +static int UnicodeError_traverse(PyUnicodeErrorObject *self, visitproc visit, void *arg) { Py_VISIT(self->encoding); @@ -1594,11 +1587,6 @@ static PyMemberDef UnicodeError_members[] = { /* * UnicodeEncodeError extends UnicodeError */ -static PyObject * -UnicodeEncodeError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - return UnicodeError_new(type, args, kwds, &PyUnicode_Type); -} static int UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds) @@ -1616,27 +1604,27 @@ UnicodeEncodeError_str(PyObject *self) Py_ssize_t end; if (PyUnicodeEncodeError_GetStart(self, &start)) - return NULL; + return NULL; if (PyUnicodeEncodeError_GetEnd(self, &end)) - return NULL; + return NULL; if (end==start+1) { - int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start]; - char badchar_str[20]; - if (badchar <= 0xff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); - else if (badchar <= 0xffff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); - else - PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); - return PyString_FromFormat( - "'%.400s' codec can't encode character u'\\%s' in position %zd: %.400s", - PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), - badchar_str, - start, - PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) - ); + int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start]; + char badchar_str[20]; + if (badchar <= 0xff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); + else if (badchar <= 0xffff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); + else + PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); + return PyString_FromFormat( + "'%.400s' codec can't encode character u'\\%s' in position %zd: %.400s", + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), + badchar_str, + start, + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); } return PyString_FromFormat( "'%.400s' codec can't encode characters in position %zd-%zd: %.400s", @@ -1655,10 +1643,10 @@ static PyTypeObject _PyExc_UnicodeEncodeError = { (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (reprfunc)UnicodeEncodeError_str, 0, 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - PyDoc_STR("Unicode encoding error."), (traverseproc)BaseException_traverse, - (inquiry)BaseException_clear, 0, 0, 0, 0, 0, UnicodeError_members, + PyDoc_STR("Unicode encoding error."), (traverseproc)UnicodeError_traverse, + (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), - (initproc)UnicodeEncodeError_init, 0, UnicodeEncodeError_new, + (initproc)UnicodeEncodeError_init, 0, BaseException_new, }; PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError; @@ -1668,18 +1656,13 @@ PyUnicodeEncodeError_Create( Py_ssize_t start, Py_ssize_t end, const char *reason) { return PyObject_CallFunction(PyExc_UnicodeEncodeError, "su#nns", - encoding, object, length, start, end, reason); + encoding, object, length, start, end, reason); } /* * UnicodeDecodeError extends UnicodeError */ -static PyObject * -UnicodeDecodeError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - return UnicodeError_new(type, args, kwds, &PyString_Type); -} static int UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds) @@ -1693,8 +1676,8 @@ UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * UnicodeDecodeError_str(PyObject *self) { - Py_ssize_t start; - Py_ssize_t end; + Py_ssize_t start = 0; + Py_ssize_t end = 0; if (PyUnicodeDecodeError_GetStart(self, &start)) return NULL; @@ -1703,17 +1686,17 @@ UnicodeDecodeError_str(PyObject *self) return NULL; if (end==start+1) { - /* FromFormat does not support %02x, so format that separately */ - char byte[4]; - PyOS_snprintf(byte, sizeof(byte), "%02x", - ((int)PyString_AS_STRING(((PyUnicodeErrorObject *)self)->object)[start])&0xff); - return PyString_FromFormat( - "'%.400s' codec can't decode byte 0x%s in position %zd: %.400s", - PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), - byte, - start, - PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) - ); + /* FromFormat does not support %02x, so format that separately */ + char byte[4]; + PyOS_snprintf(byte, sizeof(byte), "%02x", + ((int)PyString_AS_STRING(((PyUnicodeErrorObject *)self)->object)[start])&0xff); + return PyString_FromFormat( + "'%.400s' codec can't decode byte 0x%s in position %zd: %.400s", + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding), + byte, + start, + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); } return PyString_FromFormat( "'%.400s' codec can't decode bytes in position %zd-%zd: %.400s", @@ -1732,10 +1715,10 @@ static PyTypeObject _PyExc_UnicodeDecodeError = { (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (reprfunc)UnicodeDecodeError_str, 0, 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - PyDoc_STR("Unicode decoding error."), (traverseproc)BaseException_traverse, - (inquiry)BaseException_clear, 0, 0, 0, 0, 0, UnicodeError_members, + PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse, + (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), - (initproc)UnicodeDecodeError_init, 0, UnicodeDecodeError_new, + (initproc)UnicodeDecodeError_init, 0, BaseException_new, }; PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError; @@ -1748,30 +1731,13 @@ PyUnicodeDecodeError_Create( assert(start < INT_MAX); assert(end < INT_MAX); return PyObject_CallFunction(PyExc_UnicodeDecodeError, "ss#nns", - encoding, object, length, start, end, reason); + encoding, object, length, start, end, reason); } /* * UnicodeTranslateError extends UnicodeError */ -static PyObject * -UnicodeTranslateError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyUnicodeErrorObject *self = NULL; - - self = (PyUnicodeErrorObject *)BaseException_new(type, args, kwds); - if (!self) - return NULL; - - MAKE_IT_NONE(self->encoding); - MAKE_IT_NONE(self->object); - MAKE_IT_NONE(self->start); - MAKE_IT_NONE(self->end); - MAKE_IT_NONE(self->reason); - - return (PyObject *)self; -} static int UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args, @@ -1793,7 +1759,7 @@ UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args, self->object = self->start = self->end = self->reason = NULL; return -1; } - + Py_INCREF(self->object); Py_INCREF(self->start); Py_INCREF(self->end); @@ -1810,26 +1776,26 @@ UnicodeTranslateError_str(PyObject *self) Py_ssize_t end; if (PyUnicodeTranslateError_GetStart(self, &start)) - return NULL; + return NULL; if (PyUnicodeTranslateError_GetEnd(self, &end)) - return NULL; + return NULL; if (end==start+1) { - int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start]; - char badchar_str[20]; - if (badchar <= 0xff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); - else if (badchar <= 0xffff) - PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); - else - PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); - return PyString_FromFormat( + int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start]; + char badchar_str[20]; + if (badchar <= 0xff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar); + else if (badchar <= 0xffff) + PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar); + else + PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar); + return PyString_FromFormat( "can't translate character u'\\%s' in position %zd: %.400s", - badchar_str, - start, - PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) - ); + badchar_str, + start, + PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason) + ); } return PyString_FromFormat( "can't translate characters in position %zd-%zd: %.400s", @@ -1850,7 +1816,7 @@ static PyTypeObject _PyExc_UnicodeTranslateError = { PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse, (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), - (initproc)UnicodeTranslateError_init, 0, UnicodeTranslateError_new, + (initproc)UnicodeTranslateError_init, 0, BaseException_new, }; PyObject *PyExc_UnicodeTranslateError = (PyObject *)&_PyExc_UnicodeTranslateError; @@ -1860,7 +1826,7 @@ PyUnicodeTranslateError_Create( Py_ssize_t start, Py_ssize_t end, const char *reason) { return PyObject_CallFunction(PyExc_UnicodeTranslateError, "u#nns", - object, length, start, end, reason); + object, length, start, end, reason); } #endif @@ -2003,7 +1969,7 @@ static PyMethodDef functions[] = { Py_FatalError("Module dictionary insertion problem."); PyMODINIT_FUNC -_PyExc_Init(void) +_PyExc_Init(void) { PyObject *m, *bltinmod, *bdict; |