diff options
Diffstat (limited to 'Python/errors.c')
| -rw-r--r-- | Python/errors.c | 144 | 
1 files changed, 97 insertions, 47 deletions
| diff --git a/Python/errors.c b/Python/errors.c index 6cc0c20..918f4df 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -52,6 +52,20 @@ PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)      Py_XDECREF(oldtraceback);  } +static PyObject* +_PyErr_CreateException(PyObject *exception, PyObject *value) +{ +    if (value == NULL || value == Py_None) { +        return _PyObject_CallNoArg(exception); +    } +    else if (PyTuple_Check(value)) { +        return PyObject_Call(exception, value, NULL); +    } +    else { +        return _PyObject_CallArg1(exception, value); +    } +} +  void  PyErr_SetObject(PyObject *exception, PyObject *value)  { @@ -66,6 +80,7 @@ PyErr_SetObject(PyObject *exception, PyObject *value)                       exception);          return;      } +      Py_XINCREF(value);      exc_value = tstate->exc_value;      if (exc_value != NULL && exc_value != Py_None) { @@ -73,28 +88,21 @@ PyErr_SetObject(PyObject *exception, PyObject *value)          Py_INCREF(exc_value);          if (value == NULL || !PyExceptionInstance_Check(value)) {              /* We must normalize the value right now */ -            PyObject *args, *fixed_value; +            PyObject *fixed_value; -            /* Issue #23571: PyEval_CallObject() must not be called with an +            /* Issue #23571: functions must not be called with an                 exception set */              PyErr_Clear(); -            if (value == NULL || value == Py_None) -                args = PyTuple_New(0); -            else if (PyTuple_Check(value)) { -                Py_INCREF(value); -                args = value; -            } -            else -                args = PyTuple_Pack(1, value); -            fixed_value = args ? -                PyEval_CallObject(exception, args) : NULL; -            Py_XDECREF(args); +            fixed_value = _PyErr_CreateException(exception, value);              Py_XDECREF(value); -            if (fixed_value == NULL) +            if (fixed_value == NULL) {                  return; +            } +              value = fixed_value;          } +          /* Avoid reference cycles through the context chain.             This is O(chain length) but context chains are             usually very short. Sensitive readers may try @@ -110,7 +118,8 @@ PyErr_SetObject(PyObject *exception, PyObject *value)                  o = context;              }              PyException_SetContext(value, exc_value); -        } else { +        } +        else {              Py_DECREF(exc_value);          }      } @@ -258,25 +267,15 @@ PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)             class.          */          if (!inclass || !is_subclass) { -            PyObject *args, *res; +            PyObject *fixed_value; -            if (value == Py_None) -                args = PyTuple_New(0); -            else if (PyTuple_Check(value)) { -                Py_INCREF(value); -                args = value; +            fixed_value = _PyErr_CreateException(type, value); +            if (fixed_value == NULL) { +                goto finally;              } -            else -                args = PyTuple_Pack(1, value); -            if (args == NULL) -                goto finally; -            res = PyEval_CallObject(type, args); -            Py_DECREF(args); -            if (res == NULL) -                goto finally;              Py_DECREF(value); -            value = res; +            value = fixed_value;          }          /* if the class of the instance doesn't exactly match the             class of the type, believe the instance @@ -402,6 +401,47 @@ _PyErr_ChainExceptions(PyObject *exc, PyObject *val, PyObject *tb)      }  } +static PyObject * +_PyErr_FormatVFromCause(PyObject *exception, const char *format, va_list vargs) +{ +    PyObject *exc, *val, *val2, *tb; + +    assert(PyErr_Occurred()); +    PyErr_Fetch(&exc, &val, &tb); +    PyErr_NormalizeException(&exc, &val, &tb); +    if (tb != NULL) { +        PyException_SetTraceback(val, tb); +        Py_DECREF(tb); +    } +    Py_DECREF(exc); +    assert(!PyErr_Occurred()); + +    PyErr_FormatV(exception, format, vargs); + +    PyErr_Fetch(&exc, &val2, &tb); +    PyErr_NormalizeException(&exc, &val2, &tb); +    Py_INCREF(val); +    PyException_SetCause(val2, val); +    PyException_SetContext(val2, val); +    PyErr_Restore(exc, val2, tb); + +    return NULL; +} + +PyObject * +_PyErr_FormatFromCause(PyObject *exception, const char *format, ...) +{ +    va_list vargs; +#ifdef HAVE_STDARG_PROTOTYPES +    va_start(vargs, format); +#else +    va_start(vargs); +#endif +    _PyErr_FormatVFromCause(exception, format, vargs); +    va_end(vargs); +    return NULL; +} +  /* Convenience functions to set a type error exception and return 0 */  int @@ -701,51 +741,61 @@ PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(  #endif /* MS_WINDOWS */  PyObject * -PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) +PyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg, +    PyObject *name, PyObject *path)  { -    PyObject *args, *kwargs, *error; +    int issubclass; +    PyObject *kwargs, *error; -    if (msg == NULL) +    issubclass = PyObject_IsSubclass(exception, PyExc_ImportError); +    if (issubclass < 0) {          return NULL; - -    args = PyTuple_New(1); -    if (args == NULL) +    } +    else if (!issubclass) { +        PyErr_SetString(PyExc_TypeError, "expected a subclass of ImportError");          return NULL; +    } -    kwargs = PyDict_New(); -    if (kwargs == NULL) { -        Py_DECREF(args); +    if (msg == NULL) { +        PyErr_SetString(PyExc_TypeError, "expected a message argument");          return NULL;      }      if (name == NULL) {          name = Py_None;      } -      if (path == NULL) {          path = Py_None;      } -    Py_INCREF(msg); -    PyTuple_SET_ITEM(args, 0, msg); - -    if (PyDict_SetItemString(kwargs, "name", name) < 0) +    kwargs = PyDict_New(); +    if (kwargs == NULL) { +        return NULL; +    } +    if (PyDict_SetItemString(kwargs, "name", name) < 0) {          goto done; -    if (PyDict_SetItemString(kwargs, "path", path) < 0) +    } +    if (PyDict_SetItemString(kwargs, "path", path) < 0) {          goto done; +    } -    error = PyObject_Call(PyExc_ImportError, args, kwargs); +    error = _PyObject_FastCallDict(exception, &msg, 1, kwargs);      if (error != NULL) {          PyErr_SetObject((PyObject *)Py_TYPE(error), error);          Py_DECREF(error);      }  done: -    Py_DECREF(args);      Py_DECREF(kwargs);      return NULL;  } +PyObject * +PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) +{ +    return PyErr_SetImportErrorSubclass(PyExc_ImportError, msg, name, path); +} +  void  _PyErr_BadInternalCall(const char *filename, int lineno)  { | 
