Exemple #1
0
PyObject* PyCodec_StrictErrors(PyObject* exc) noexcept {
    if (PyExceptionInstance_Check(exc))
        PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
    else
        PyErr_SetString(PyExc_TypeError, "codec must pass exception instance");
    return NULL;
}
Exemple #2
0
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_IMPLICIT( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb )
{
    CHECK_OBJECT( *exception_type );
    CHECK_OBJECT( *exception_value );
    *exception_tb = NULL;

    // Non-empty tuple exceptions are the first element.
    while (unlikely( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 ))
    {
        *exception_type = PyTuple_GET_ITEM( *exception_type, 0 );
    }

    if ( PyExceptionClass_Check( *exception_type ) )
    {
        return;
    }
    else if ( PyExceptionInstance_Check( *exception_type ) )
    {
        // The type is rather a value, so we are overriding it here.
        *exception_value = *exception_type;
        *exception_type = PyExceptionInstance_Class( *exception_type );
        Py_INCREF( *exception_type );

        return;
    }
    else
    {
        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name );
        FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
        return;
    }
}
Exemple #3
0
int
PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
{
    if (err == NULL || exc == NULL) {
        /* maybe caused by "import exceptions" that failed early on */
        return 0;
    }
    if (PyTuple_Check(exc)) {
        Py_ssize_t i, n;
        n = PyTuple_Size(exc);
        for (i = 0; i < n; i++) {
            /* Test recursively */
             if (PyErr_GivenExceptionMatches(
                 err, PyTuple_GET_ITEM(exc, i)))
             {
                 return 1;
             }
        }
        return 0;
    }
    /* err might be an instance, so check its class. */
    if (PyExceptionInstance_Check(err))
        err = PyExceptionInstance_Class(err);

    if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
        return PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc);
    }

    return err == exc;
}
Exemple #4
0
int
PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
{
    if (err == NULL || exc == NULL) {
        /* maybe caused by "import exceptions" that failed early on */
        return 0;
    }
    if (PyTuple_Check(exc)) {
        Py_ssize_t i, n;
        n = PyTuple_Size(exc);
        for (i = 0; i < n; i++) {
            /* Test recursively */
            if (PyErr_GivenExceptionMatches(
                        err, PyTuple_GET_ITEM(exc, i)))
            {
                return 1;
            }
        }
        return 0;
    }
    /* err might be an instance, so check its class. */
    if (PyExceptionInstance_Check(err))
        err = PyExceptionInstance_Class(err);

    if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
        /* problems here!?  not sure PyObject_IsSubclass expects to
           be called with an exception pending... */
        return PyObject_IsSubclass(err, exc);
    }

    return err == exc;
}
Exemple #5
0
static PyObject *
gen_throw(PyGenObject *gen, PyObject *typ, PyObject *val, PyObject *tb)
{
	/* First, check the traceback argument, replacing None with
	   NULL. */
	if (tb == Py_None)
		tb = NULL;
	else if (tb != NULL && !PyTraceBack_Check(tb)) {
		PyErr_SetString(PyExc_TypeError,
			"throw() third argument must be a traceback object");
		return NULL;
	}

	Py_INCREF(typ);
	Py_XINCREF(val);
	Py_XINCREF(tb);

	if (PyExceptionClass_Check(typ)) {
		PyErr_NormalizeException(&typ, &val, &tb);
	}

	else if (PyExceptionInstance_Check(typ)) {
		/* Raising an instance.  The value should be a dummy. */
		if (val && val != Py_None) {
			PyErr_SetString(PyExc_TypeError,
			  "instance exception may not have a separate value");
			goto failed_throw;
		}
		else {
			/* Normalize to raise <class>, <instance> */
			Py_XDECREF(val);
			val = typ;
			typ = PyExceptionInstance_Class(typ);
			Py_INCREF(typ);
		}
	}
	else {
		/* Not something you can raise.  throw() fails. */
		PyErr_Format(PyExc_TypeError,
			     "exceptions must be classes, or instances, not %s",
			     typ->ob_type->tp_name);
			goto failed_throw;
	}

	PyErr_Restore(typ, val, tb);
	return gen_send_ex(gen, Py_None, 1);

failed_throw:
	/* Didn't use our arguments, so restore their original refcounts */
	Py_DECREF(typ);
	Py_XDECREF(val);
	Py_XDECREF(tb);
	return NULL;
}
// takes the three arguments of a `raise' and produces the ExcInfo to throw
ExcInfo excInfoForRaise(Box* type, Box* value, Box* tb) {
    assert(type && value && tb); // use None for default behavior, not nullptr
    // TODO switch this to PyErr_Normalize

    if (tb == None) {
        tb = NULL;
    } else if (tb != NULL && !PyTraceBack_Check(tb)) {
        raiseExcHelper(TypeError, "raise: arg 3 must be a traceback or None");
    }


    /* Next, repeatedly, replace a tuple exception with its first item */
    while (PyTuple_Check(type) && PyTuple_Size(type) > 0) {
        PyObject* tmp = type;
        type = PyTuple_GET_ITEM(type, 0);
        Py_INCREF(type);
        Py_DECREF(tmp);
    }

    if (PyExceptionClass_Check(type)) {
        PyErr_NormalizeException(&type, &value, &tb);

        if (!PyExceptionInstance_Check(value)) {
            raiseExcHelper(TypeError, "calling %s() should have returned an instance of "
                                      "BaseException, not '%s'",
                           ((PyTypeObject*)type)->tp_name, Py_TYPE(value)->tp_name);
        }
    } else if (PyExceptionInstance_Check(type)) {
        /* Raising an instance.  The value should be a dummy. */
        if (value != Py_None) {
            raiseExcHelper(TypeError, "instance exception may not have a separate value");
        } else {
            /* Normalize to raise <class>, <instance> */
            Py_DECREF(value);
            value = type;
            type = PyExceptionInstance_Class(type);
            Py_INCREF(type);
        }
    } else {
        /* Not something you can raise.  You get an exception
           anyway, just not what you specified :-) */
        raiseExcHelper(TypeError, "exceptions must be old-style classes or "
                                  "derived from BaseException, not %s",
                       type->cls->tp_name);
    }

    assert(PyExceptionClass_Check(type));

    if (tb == NULL) {
        tb = None;
    }

    return ExcInfo(type, value, tb);
}
Exemple #7
0
static PyObject* compose_throw(PyComposeObject* self, PyObject* arg) {
    PyObject* exc_type = NULL, *exc_value = NULL, *exc_tb = NULL;

    if(!PyArg_ParseTuple(arg, "O|OO", &exc_type, &exc_value, &exc_tb)) //borrowed refs
        return NULL;

    if(PyExceptionInstance_Check(exc_type)) { // e.g. throw(Exception())
        exc_value = exc_type;
        exc_type = PyExceptionInstance_Class(exc_type); // borrowed ref
    }

    return _compose_go_with_frame(self, exc_type, exc_value, exc_tb);
}
Exemple #8
0
int
PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
{
    if (err == NULL || exc == NULL) {
        /* maybe caused by "import exceptions" that failed early on */
        return 0;
    }
    if (PyTuple_Check(exc)) {
        Py_ssize_t i, n;
        n = PyTuple_Size(exc);
        for (i = 0; i < n; i++) {
            /* Test recursively */
             if (PyErr_GivenExceptionMatches(
                 err, PyTuple_GET_ITEM(exc, i)))
             {
                 return 1;
             }
        }
        return 0;
    }
    /* err might be an instance, so check its class. */
    if (PyExceptionInstance_Check(err))
        err = PyExceptionInstance_Class(err);

    if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
        int res = 0, reclimit;
        PyObject *exception, *value, *tb;
        PyErr_Fetch(&exception, &value, &tb);
        /* Temporarily bump the recursion limit, so that in the most
           common case PyObject_IsSubclass will not raise a recursion
           error we have to ignore anyway.  Don't do it when the limit
           is already insanely high, to avoid overflow */
        reclimit = Py_GetRecursionLimit();
        if (reclimit < (1 << 30))
            Py_SetRecursionLimit(reclimit + 5);
        res = PyObject_IsSubclass(err, exc);
        Py_SetRecursionLimit(reclimit);
        /* This function must not fail, so print the error here */
        if (res == -1) {
            PyErr_WriteUnraisable(err);
            res = 0;
        }
        PyErr_Restore(exception, value, tb);
        return res;
    }

    return err == exc;
}
Exemple #9
0
NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_GENERATOR( PyObject *exception_value )
{
    CHECK_OBJECT( exception_value );

    // We need to check the class.
    if ( PyExceptionInstance_Check( exception_value ) )
    {
        exception_value = PyExceptionInstance_Class( exception_value );
    }

    // Lets be optimistic. If it matches, we would be wasting our time.
    if ( exception_value == PyExc_GeneratorExit || exception_value == PyExc_StopIteration )
    {
        return true;
    }

    if ( PyExceptionClass_Check( exception_value ) )
    {
        // Save the current exception, if any, we must preserve it.
        PyObject *save_exception_type, *save_exception_value;
        PyTracebackObject *save_exception_tb;
        FETCH_ERROR_OCCURRED( &save_exception_type, &save_exception_value, &save_exception_tb );

        int res = PyObject_IsSubclass( exception_value, PyExc_GeneratorExit );

        // This function must not fail, so print the error here */
        if (unlikely( res == -1 ))
        {
            PyErr_WriteUnraisable( exception_value );
        }

        if (res == 1) return true;

        res = PyObject_IsSubclass( exception_value, PyExc_StopIteration );

        // This function must not fail, so print the error here */
        if (unlikely( res == -1 ))
        {
            PyErr_WriteUnraisable( exception_value );
        }

        RESTORE_ERROR_OCCURRED( save_exception_type, save_exception_value, save_exception_tb );

        return res == 1;
    }

    return false;
}
Exemple #10
0
int
PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
{
    if (err == NULL || exc == NULL) {
        /* maybe caused by "import exceptions" that failed early on */
        return 0;
    }
    if (PyTuple_Check(exc)) {
        Py_ssize_t i, n;
        n = PyTuple_Size(exc);
        for (i = 0; i < n; i++) {
            /* Test recursively */
             if (PyErr_GivenExceptionMatches(
                 err, PyTuple_GET_ITEM(exc, i)))
             {
                 return 1;
             }
        }
        return 0;
    }
    /* err might be an instance, so check its class. */
    if (PyExceptionInstance_Check(err))
        err = PyExceptionInstance_Class(err);

    if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
        int res = 0;
        PyObject *exception, *value, *tb;
        PyErr_Fetch(&exception, &value, &tb);
        /* PyObject_IsSubclass() can recurse and therefore is
           not safe (see test_bad_getattr in test.pickletester). */
        res = PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc);
        /* This function must not fail, so print the error here */
        if (res == -1) {
            PyErr_WriteUnraisable(err);
            res = 0;
        }
        PyErr_Restore(exception, value, tb);
        return res;
    }

    return err == exc;
}
Exemple #11
0
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_VALUE_NO_NORMALIZE( PyObject *exception_type, PyObject *value, PyObject *tb )
{
    PyTracebackObject *traceback = (PyTracebackObject *)tb;

    assertObject( exception_type );
    assert( !PyTuple_Check( exception_type ) );

    if ( PyExceptionClass_Check( exception_type ) )
    {
        throw PythonException(
            INCREASE_REFCOUNT( exception_type ),
            INCREASE_REFCOUNT( value ),
            INCREASE_REFCOUNT_X( traceback )
        );
    }
    else if ( PyExceptionInstance_Check( exception_type ) )
    {
        assert ( value == NULL || value == Py_None );

        // The type is rather a value, so we are overriding it here.
        value = exception_type;
        exception_type = PyExceptionInstance_Class( exception_type );

        throw PythonException(
            INCREASE_REFCOUNT( exception_type ),
            INCREASE_REFCOUNT( value ),
            INCREASE_REFCOUNT_X( traceback )
        );
    }
    else
    {
        assert( false );

        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name );

        throw PythonException();
    }
}
Exemple #12
0
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_TYPE( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb )
{
    *exception_value = NULL;
    *exception_tb = NULL;

#if PYTHON_VERSION < 300
    // Next, repeatedly, replace a tuple exception with its first item
    while( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 )
    {
         PyObject *tmp = *exception_type;
         *exception_type = PyTuple_GET_ITEM( *exception_type, 0 );
         Py_INCREF( *exception_type );
         Py_DECREF( tmp );
    }
#endif

    if ( PyExceptionClass_Check( *exception_type ) )
    {
        NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb );
#if PYTHON_VERSION >= 270
        if (unlikely( !PyExceptionInstance_Check( *exception_value ) ))
        {
            PyErr_Format(
                PyExc_TypeError,
                "calling %s() should have returned an instance of BaseException, not '%s'",
                ((PyTypeObject *)*exception_type)->tp_name,
                Py_TYPE( *exception_value )->tp_name
            );

            Py_DECREF( *exception_type );
            Py_DECREF( *exception_value );

            FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
            return;
        }
#endif

#if PYTHON_VERSION >= 300
        CHAIN_EXCEPTION( *exception_type, *exception_value );
#endif
        return;
    }
    else if ( PyExceptionInstance_Check( *exception_type ) )
    {
        *exception_value = *exception_type;
        *exception_type = PyExceptionInstance_Class( *exception_type );
        Py_INCREF( *exception_type );

#if PYTHON_VERSION >= 300
        CHAIN_EXCEPTION( *exception_type, *exception_value );

        // TODO: Ever true?
        if ( *exception_tb )
        {
            PyTracebackObject *prev = (PyTracebackObject *)PyException_GetTraceback( *exception_value );

            if ( prev != NULL )
            {
                assert( (*exception_tb)->tb_next == NULL );
                (*exception_tb)->tb_next = prev;
            }

            PyException_SetTraceback( *exception_value, (PyObject *)(*exception_tb ? *exception_tb : (PyTracebackObject *)Py_None ) );
        }

        *exception_tb = (PyTracebackObject *)PyException_GetTraceback( *exception_value );
#endif

        return;
    }
    else
    {
        Py_DECREF( *exception_type );

        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( *exception_type )->tp_name );
        FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
        return;
    }
}
Exemple #13
0
NUITKA_MAY_BE_UNUSED static inline void RAISE_EXCEPTION_WITH_TRACEBACK( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb )
{
    CHECK_OBJECT( *exception_type );
    CHECK_OBJECT( *exception_value );

    if ( *exception_tb == (PyTracebackObject *)Py_None )
    {
        Py_DECREF( *exception_tb );
        *exception_tb = NULL;
    }

    // Non-empty tuple exceptions are the first element.
    while (unlikely( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 ))
    {
        *exception_type = PyTuple_GET_ITEM( *exception_type, 0 );
    }

    if ( PyExceptionClass_Check( *exception_type ) )
    {
        NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb );
#if PYTHON_VERSION >= 270
        if (unlikely( !PyExceptionInstance_Check( *exception_value ) ))
        {
            PyErr_Format(
                PyExc_TypeError,
                "calling %s() should have returned an instance of BaseException, not '%s'",
                ((PyTypeObject *)*exception_type)->tp_name,
                Py_TYPE( *exception_value )->tp_name
            );

            Py_DECREF( *exception_type );
            Py_XDECREF( *exception_value );
            Py_XDECREF( *exception_tb );

            FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
        }
#endif

        return;
    }
    else if ( PyExceptionInstance_Check( *exception_type ) )
    {
        if (unlikely( *exception_value != NULL && *exception_value != Py_None ))
        {
            PyErr_Format(
                PyExc_TypeError,
                "instance exception may not have a separate value"
            );

            Py_DECREF( *exception_type );
            Py_XDECREF( *exception_value );
            Py_XDECREF( *exception_tb );

            FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );

            return;
        }

        // The type is rather a value, so we are overriding it here.
        *exception_value = *exception_type;
        *exception_type = PyExceptionInstance_Class( *exception_type );
        Py_INCREF( *exception_type );

        return;
    }
    else
    {
        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name );
        FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
        return;
    }
}
Exemple #14
0
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_CAUSE( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb, PyObject *exception_cause  )
{
    CHECK_OBJECT( *exception_type );
    CHECK_OBJECT( exception_cause );
    *exception_value = NULL;
    *exception_tb = NULL;

#if PYTHON_VERSION >= 330
    // None is not a cause.
    if ( exception_cause == Py_None )
    {
        Py_DECREF( exception_cause );
        exception_cause = NULL;
    }
    else
#endif
    if ( PyExceptionClass_Check( exception_cause ) )
    {
        PyObject *old_exception_cause = exception_cause;
        exception_cause = PyObject_CallObject( exception_cause, NULL );
        Py_DECREF( old_exception_cause );

        if (unlikely( exception_cause == NULL ))
        {
            Py_DECREF( *exception_type );
            Py_XDECREF( *exception_tb );

            FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );

            return;
        }
    }

#if PYTHON_VERSION >= 330
    if (unlikely( exception_cause != NULL && !PyExceptionInstance_Check( exception_cause ) ))
#else
    if (unlikely( !PyExceptionInstance_Check( exception_cause ) ))
#endif
    {
        Py_DECREF( *exception_type );
        Py_XDECREF( *exception_tb );
        Py_XDECREF( exception_cause );

        PyErr_Format( PyExc_TypeError, "exception causes must derive from BaseException" );

        FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
        return;
    }

    if ( PyExceptionClass_Check( *exception_type ) )
    {
        NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb );

        if (unlikely( !PyExceptionInstance_Check( *exception_value ) ))
        {
            Py_DECREF( *exception_type );
            Py_XDECREF( *exception_value );
            Py_DECREF( *exception_tb );
            Py_XDECREF( exception_cause );

            PyErr_Format(
                PyExc_TypeError,
                "calling %s() should have returned an instance of BaseException, not '%s'",
                ((PyTypeObject *)exception_type)->tp_name,
                Py_TYPE( *exception_value )->tp_name
            );

            FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
            return;
        }

        PyException_SetCause( *exception_value, exception_cause );

#if PYTHON_VERSION >= 300
        CHAIN_EXCEPTION( *exception_type, *exception_value );
#endif
        return;
    }
    else if ( PyExceptionInstance_Check( *exception_type ) )
    {
        *exception_value = *exception_type;
        *exception_type = PyExceptionInstance_Class( *exception_type );
        Py_INCREF( *exception_type );

        PyException_SetCause( *exception_value, exception_cause );

#if PYTHON_VERSION >= 300
        CHAIN_EXCEPTION( *exception_type, *exception_value );
#endif

        return;
    }
    else
    {
        Py_DECREF( *exception_type );
        Py_XDECREF( exception_cause );

        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name );
        FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb );

        return;
    }
}
Exemple #15
0
/* Used in many places to normalize a raised exception, including in
   eval_code2(), do_raise(), and PyErr_Print()

   XXX: should PyErr_NormalizeException() also call
            PyException_SetTraceback() with the resulting value and tb?
*/
void
PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
{
    int recursion_depth = 0;
    PyObject *type, *value, *initial_tb;

  restart:
    type = *exc;
    if (type == NULL) {
        /* There was no exception, so nothing to do. */
        return;
    }

    value = *val;
    /* If PyErr_SetNone() was used, the value will have been actually
       set to NULL.
    */
    if (!value) {
        value = Py_None;
        Py_INCREF(value);
    }

    /* Normalize the exception so that if the type is a class, the
       value will be an instance.
    */
    if (PyExceptionClass_Check(type)) {
        PyObject *inclass = NULL;
        int is_subclass = 0;

        if (PyExceptionInstance_Check(value)) {
            inclass = PyExceptionInstance_Class(value);
            is_subclass = PyObject_IsSubclass(inclass, type);
            if (is_subclass < 0) {
                goto error;
            }
        }

        /* If the value was not an instance, or is not an instance
           whose class is (or is derived from) type, then use the
           value as an argument to instantiation of the type
           class.
        */
        if (!is_subclass) {
            PyObject *fixed_value = _PyErr_CreateException(type, value);
            if (fixed_value == NULL) {
                goto error;
            }
            Py_DECREF(value);
            value = fixed_value;
        }
        /* If the class of the instance doesn't exactly match the
           class of the type, believe the instance.
        */
        else if (inclass != type) {
            Py_INCREF(inclass);
            Py_DECREF(type);
            type = inclass;
        }
    }
    *exc = type;
    *val = value;
    return;

  error:
    Py_DECREF(type);
    Py_DECREF(value);
    recursion_depth++;
    if (recursion_depth == Py_NORMALIZE_RECURSION_LIMIT) {
        PyErr_SetString(PyExc_RecursionError, "maximum recursion depth "
                        "exceeded while normalizing an exception");
    }
    /* If the new exception doesn't set a traceback and the old
       exception had a traceback, use the old traceback for the
       new exception.  It's better than nothing.
    */
    initial_tb = *tb;
    PyErr_Fetch(exc, val, tb);
    assert(*exc != NULL);
    if (initial_tb != NULL) {
        if (*tb == NULL)
            *tb = initial_tb;
        else
            Py_DECREF(initial_tb);
    }
    /* Abort when Py_NORMALIZE_RECURSION_LIMIT has been exceeded, and the
       corresponding RecursionError could not be normalized, and the
       MemoryError raised when normalize this RecursionError could not be
       normalized. */
    if (recursion_depth >= Py_NORMALIZE_RECURSION_LIMIT + 2) {
        if (PyErr_GivenExceptionMatches(*exc, PyExc_MemoryError)) {
            Py_FatalError("Cannot recover from MemoryErrors "
                          "while normalizing exceptions.");
        }
        else {
            Py_FatalError("Cannot recover from the recursive normalization "
                          "of an exception.");
        }
    }
    goto restart;
}
Exemple #16
0
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_CAUSE( PyObject *exception_type, PyObject *exception_cause, PyObject *exception_tb )
{
    PyTracebackObject *traceback = (PyTracebackObject *)exception_tb;

    assertObject( exception_type );
    assertObject( exception_cause );

#if PYTHON_VERSION >= 330
    // None is not a cause.
    if ( exception_cause == Py_None )
    {
        exception_cause = NULL;
    }
    else
#endif
        if ( PyExceptionClass_Check( exception_cause ) )
        {
            exception_cause = PyObject_CallObject( exception_cause, NULL );

            if (unlikely( exception_cause == NULL ))
            {
                throw PythonException();
            }
        }
        else
        {
            Py_INCREF( exception_cause );
        }

#if PYTHON_VERSION >= 330
    if (unlikely( exception_cause != NULL && !PyExceptionInstance_Check( exception_cause ) ))
#else
    if (unlikely( !PyExceptionInstance_Check( exception_cause ) ))
#endif
    {
        Py_XDECREF( exception_cause );

        PyErr_Format( PyExc_TypeError, "exception causes must derive from BaseException" );
        throw PythonException();
    }


    if ( PyExceptionClass_Check( exception_type ) )
    {
        PyObject *value = NULL;

        Py_INCREF( exception_type );
        Py_INCREF( traceback );

        NORMALIZE_EXCEPTION( &exception_type, &value, &traceback );
        if (unlikely( !PyExceptionInstance_Check( value ) ))
        {
            Py_DECREF( exception_type );
            Py_XDECREF( value );
            Py_DECREF( traceback );
            Py_XDECREF( exception_cause );

            PyErr_Format(
                PyExc_TypeError,
                "calling %s() should have returned an instance of BaseException, not '%s'",
                ((PyTypeObject *)exception_type)->tp_name,
                Py_TYPE( value )->tp_name
            );

            throw PythonException();
        }

        PythonException to_throw( exception_type, value, traceback );
        to_throw.setCause( exception_cause );
        throw to_throw;
    }
    else if ( PyExceptionInstance_Check( exception_type ) )
    {
        Py_XDECREF( exception_cause );

        throw PythonException(
            INCREASE_REFCOUNT( PyExceptionInstance_Class( exception_type ) ),
            INCREASE_REFCOUNT( exception_type ),
            INCREASE_REFCOUNT( traceback )
        );
    }
    else
    {
        Py_XDECREF( exception_cause );

        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name );

        PythonException to_throw;
        to_throw.setTraceback( INCREASE_REFCOUNT( traceback ) );

        throw to_throw;
    }
}
Exemple #17
0
static PyObject *
Fiber_func_throw(Fiber *self, PyObject *args)
{
    Fiber *current;
    PyObject *typ, *val, *tb;

    val = tb = NULL;

    if (!PyArg_ParseTuple(args, "O|OO:throw", &typ, &val, &tb)) {
	return NULL;
    }

    /* First, check the traceback argument, replacing None, with NULL */
    if (tb == Py_None) {
        tb = NULL;
    } else if (tb != NULL && !PyTraceBack_Check(tb)) {
	PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback object");
	return NULL;
    }

    Py_INCREF(typ);
    Py_XINCREF(val);
    Py_XINCREF(tb);

    if (PyExceptionClass_Check(typ)) {
        PyErr_NormalizeException(&typ, &val, &tb);
    } else if (PyExceptionInstance_Check(typ)) {
        /* Raising an instance. The value should be a dummy. */
        if (val && val != Py_None) {
	    PyErr_SetString(PyExc_TypeError, "instance exceptions cannot have a separate value");
	    goto error;
	} else {
	    /* Normalize to raise <class>, <instance> */
	    Py_XDECREF(val);
            val = typ;
            typ = PyExceptionInstance_Class(typ);
	    Py_INCREF(typ);
	}
    } else {
	/* Not something you can raise. throw() fails. */
        PyErr_Format(PyExc_TypeError, "exceptions must be classes, or instances, not %s", Py_TYPE(typ)->tp_name);
	goto error;
    }

    if (!CHECK_STATE) {
        goto error;
    }

    current = _global_state.current;
    if (self == current) {
        PyErr_SetString(PyExc_FiberError, "cannot throw from a Fiber to itself");
        goto error;
    }

    if (self->stacklet_h == EMPTY_STACKLET_HANDLE) {
        PyErr_SetString(PyExc_FiberError, "Fiber has ended");
        goto error;
    }

    if (self->thread_h != current->thread_h) {
        PyErr_SetString(PyExc_FiberError, "cannot switch to a Fiber on a different thread");
        return NULL;
    }

    /* set error and do a switch with NULL as the value */
    PyErr_Restore(typ, val, tb);

    return do_switch(self, NULL);

error:
    /* Didn't use our arguments, so restore their original refcounts */
    Py_DECREF(typ);
    Py_XDECREF(val);
    Py_XDECREF(tb);
    return NULL;
}
Exemple #18
0
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_VALUE( PyObject *exception_type, PyObject *value, PyObject *exception_tb )
{
    assertObject( exception_type );
    PyTracebackObject *traceback = (PyTracebackObject *)exception_tb;

    // Non-empty tuple exceptions are the first element.
    while (unlikely( PyTuple_Check( exception_type ) && PyTuple_Size( exception_type ) > 0 ))
    {
        exception_type = PyTuple_GET_ITEM( exception_type, 0 );
    }

    if ( PyExceptionClass_Check( exception_type ) )
    {
        Py_INCREF( exception_type );
        Py_XINCREF( value );
        Py_XINCREF( traceback );

        NORMALIZE_EXCEPTION( &exception_type, &value, &traceback );
#if PYTHON_VERSION >= 270
        if (unlikely( !PyExceptionInstance_Check( value ) ))
        {
            PyErr_Format(
                PyExc_TypeError,
                "calling %s() should have returned an instance of BaseException, not '%s'",
                ((PyTypeObject *)exception_type)->tp_name,
                Py_TYPE( value )->tp_name
            );

            Py_DECREF( exception_type );
            Py_XDECREF( value );
            Py_XDECREF( traceback );

            throw PythonException();
        }
#endif

        throw PythonException(
            exception_type,
            value,
            traceback
        );
    }
    else if ( PyExceptionInstance_Check( exception_type ) )
    {
        if (unlikely( value != NULL && value != Py_None ))
        {
            PyErr_Format(
                PyExc_TypeError,
                "instance exception may not have a separate value"
            );

            throw PythonException();
        }

        // The type is rather a value, so we are overriding it here.
        value = exception_type;
        exception_type = PyExceptionInstance_Class( exception_type );

        throw PythonException(
            INCREASE_REFCOUNT( exception_type ),
            INCREASE_REFCOUNT( value ),
            INCREASE_REFCOUNT_X( traceback )
        );
    }
    else
    {
        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name );

        throw PythonException();
    }
}
Exemple #19
0
static PyObject *
gen_throw(PyGenObject *gen, PyObject *args)
{
    PyObject *typ;
    PyObject *tb = NULL;
    PyObject *val = NULL;
    PyObject *yf = _PyGen_yf(gen);
    _Py_IDENTIFIER(throw);

    if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
        return NULL;

    if (yf) {
        PyObject *ret;
        int err;
        if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
            gen->gi_running = 1;
            err = gen_close_iter(yf);
            gen->gi_running = 0;
            Py_DECREF(yf);
            if (err < 0)
                return gen_send_ex(gen, Py_None, 1, 0);
            goto throw_here;
        }
        if (PyGen_CheckExact(yf)) {
            gen->gi_running = 1;
            ret = gen_throw((PyGenObject *)yf, args);
            gen->gi_running = 0;
        } else {
            PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw);
            if (meth == NULL) {
                if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
                    Py_DECREF(yf);
                    return NULL;
                }
                PyErr_Clear();
                Py_DECREF(yf);
                goto throw_here;
            }
            gen->gi_running = 1;
            ret = PyObject_CallObject(meth, args);
            gen->gi_running = 0;
            Py_DECREF(meth);
        }
        Py_DECREF(yf);
        if (!ret) {
            PyObject *val;
            /* Pop subiterator from stack */
            ret = *(--gen->gi_frame->f_stacktop);
            assert(ret == yf);
            Py_DECREF(ret);
            /* Termination repetition of YIELD_FROM */
            gen->gi_frame->f_lasti += 2;
            if (_PyGen_FetchStopIterationValue(&val) == 0) {
                ret = gen_send_ex(gen, val, 0, 0);
                Py_DECREF(val);
            } else {
                ret = gen_send_ex(gen, Py_None, 1, 0);
            }
        }
        return ret;
    }

throw_here:
    /* First, check the traceback argument, replacing None with
       NULL. */
    if (tb == Py_None) {
        tb = NULL;
    }
    else if (tb != NULL && !PyTraceBack_Check(tb)) {
        PyErr_SetString(PyExc_TypeError,
            "throw() third argument must be a traceback object");
        return NULL;
    }

    Py_INCREF(typ);
    Py_XINCREF(val);
    Py_XINCREF(tb);

    if (PyExceptionClass_Check(typ))
        PyErr_NormalizeException(&typ, &val, &tb);

    else if (PyExceptionInstance_Check(typ)) {
        /* Raising an instance.  The value should be a dummy. */
        if (val && val != Py_None) {
            PyErr_SetString(PyExc_TypeError,
              "instance exception may not have a separate value");
            goto failed_throw;
        }
        else {
            /* Normalize to raise <class>, <instance> */
            Py_XDECREF(val);
            val = typ;
            typ = PyExceptionInstance_Class(typ);
            Py_INCREF(typ);

            if (tb == NULL)
                /* Returns NULL if there's no traceback */
                tb = PyException_GetTraceback(val);
        }
    }
    else {
        /* Not something you can raise.  throw() fails. */
        PyErr_Format(PyExc_TypeError,
                     "exceptions must be classes or instances "
                     "deriving from BaseException, not %s",
                     Py_TYPE(typ)->tp_name);
            goto failed_throw;
    }

    PyErr_Restore(typ, val, tb);
    return gen_send_ex(gen, Py_None, 1, 0);

failed_throw:
    /* Didn't use our arguments, so restore their original refcounts */
    Py_DECREF(typ);
    Py_XDECREF(val);
    Py_XDECREF(tb);
    return NULL;
}
Exemple #20
0
/* Used in many places to normalize a raised exception, including in
   eval_code2(), do_raise(), and PyErr_Print()

   XXX: should PyErr_NormalizeException() also call
            PyException_SetTraceback() with the resulting value and tb?
*/
void
PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
{
    PyObject *type = *exc;
    PyObject *value = *val;
    PyObject *inclass = NULL;
    PyObject *initial_tb = NULL;
    PyThreadState *tstate = NULL;

    if (type == NULL) {
        /* There was no exception, so nothing to do. */
        return;
    }

    /* If PyErr_SetNone() was used, the value will have been actually
       set to NULL.
    */
    if (!value) {
        value = Py_None;
        Py_INCREF(value);
    }

    if (PyExceptionInstance_Check(value))
        inclass = PyExceptionInstance_Class(value);

    /* Normalize the exception so that if the type is a class, the
       value will be an instance.
    */
    if (PyExceptionClass_Check(type)) {
        int is_subclass;
        if (inclass) {
            is_subclass = PyObject_IsSubclass(inclass, type);
            if (is_subclass < 0)
                goto finally;
        }
        else
            is_subclass = 0;

        /* if the value was not an instance, or is not an instance
           whose class is (or is derived from) type, then use the
           value as an argument to instantiation of the type
           class.
        */
        if (!inclass || !is_subclass) {
            PyObject *fixed_value;

            fixed_value = _PyErr_CreateException(type, value);
            if (fixed_value == NULL) {
                goto finally;
            }

            Py_DECREF(value);
            value = fixed_value;
        }
        /* if the class of the instance doesn't exactly match the
           class of the type, believe the instance
        */
        else if (inclass != type) {
            Py_DECREF(type);
            type = inclass;
            Py_INCREF(type);
        }
    }
    *exc = type;
    *val = value;
    return;
finally:
    Py_DECREF(type);
    Py_DECREF(value);
    /* If the new exception doesn't set a traceback and the old
       exception had a traceback, use the old traceback for the
       new exception.  It's better than nothing.
    */
    initial_tb = *tb;
    PyErr_Fetch(exc, val, tb);
    if (initial_tb != NULL) {
        if (*tb == NULL)
            *tb = initial_tb;
        else
            Py_DECREF(initial_tb);
    }
    /* normalize recursively */
    tstate = PyThreadState_GET();
    if (++tstate->recursion_depth > Py_GetRecursionLimit()) {
        --tstate->recursion_depth;
        /* throw away the old exception and use the recursion error instead */
        Py_INCREF(PyExc_RecursionError);
        Py_SETREF(*exc, PyExc_RecursionError);
        Py_INCREF(PyExc_RecursionErrorInst);
        Py_SETREF(*val, PyExc_RecursionErrorInst);
        /* just keeping the old traceback */
        return;
    }
    PyErr_NormalizeException(exc, val, tb);
    --tstate->recursion_depth;
}
Exemple #21
0
/* Used in many places to normalize a raised exception, including in
   eval_code2(), do_raise(), and PyErr_Print()
*/
void
PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
{
    PyObject *type = *exc;
    PyObject *value = *val;
    PyObject *inclass = NULL;
    PyObject *initial_tb = NULL;

    if (type == NULL) {
        /* There was no exception, so nothing to do. */
        return;
    }

    /* If PyErr_SetNone() was used, the value will have been actually
       set to NULL.
    */
    if (!value) {
        value = Py_None;
        Py_INCREF(value);
    }

    if (PyExceptionInstance_Check(value))
        inclass = PyExceptionInstance_Class(value);

    /* Normalize the exception so that if the type is a class, the
       value will be an instance.
    */
    if (PyExceptionClass_Check(type)) {
        /* if the value was not an instance, or is not an instance
           whose class is (or is derived from) type, then use the
           value as an argument to instantiation of the type
           class.
        */
        if (!inclass || !PyObject_IsSubclass(inclass, type)) {
            PyObject *args, *res;

            if (value == Py_None)
                args = PyTuple_New(0);
            else if (PyTuple_Check(value)) {
                Py_INCREF(value);
                args = value;
            }
            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;
        }
        /* if the class of the instance doesn't exactly match the
           class of the type, believe the instance
        */
        else if (inclass != type) {
            Py_DECREF(type);
            type = inclass;
            Py_INCREF(type);
        }
    }
    *exc = type;
    *val = value;
    return;
finally:
    Py_DECREF(type);
    Py_DECREF(value);
    /* If the new exception doesn't set a traceback and the old
       exception had a traceback, use the old traceback for the
       new exception.  It's better than nothing.
    */
    initial_tb = *tb;
    PyErr_Fetch(exc, val, tb);
    if (initial_tb != NULL) {
        if (*tb == NULL)
            *tb = initial_tb;
        else
            Py_DECREF(initial_tb);
    }
    /* normalize recursively */
    PyErr_NormalizeException(exc, val, tb);
}
Exemple #22
0
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_TYPE( PyObject *exception_type, PyObject *exception_tb )
{
    PyTracebackObject *traceback = (PyTracebackObject *)exception_tb;
    assertObject( traceback );
    assert( PyTraceBack_Check( traceback ) );
    assertObject( exception_type );

    if ( PyExceptionClass_Check( exception_type ) )
    {
        PyObject *value = NULL;

        Py_INCREF( exception_type );
        Py_XINCREF( traceback );

        NORMALIZE_EXCEPTION( &exception_type, &value, &traceback );
#if PYTHON_VERSION >= 270
        if (unlikely( !PyExceptionInstance_Check( value ) ))
        {
            Py_DECREF( exception_type );
            Py_DECREF( value );
            Py_XDECREF( traceback );

            PyErr_Format(
                PyExc_TypeError,
                "calling %s() should have returned an instance of BaseException, not '%s'",
                ((PyTypeObject *)exception_type)->tp_name,
                Py_TYPE( value )->tp_name
            );

            throw PythonException();
        }
#endif

#if PYTHON_VERSION >= 300
        CHAIN_EXCEPTION( exception_type, value );
#endif
        throw PythonException(
            exception_type,
            value,
            traceback
        );
    }
    else if ( PyExceptionInstance_Check( exception_type ) )
    {
        PyObject *value = exception_type;
        exception_type = PyExceptionInstance_Class( exception_type );

#if PYTHON_VERSION >= 300
        CHAIN_EXCEPTION( exception_type, value );

        PyTracebackObject *prev = (PyTracebackObject *)PyException_GetTraceback( value );

        if ( prev != NULL )
        {
            assert( traceback->tb_next == NULL );
            traceback->tb_next = prev;
        }

        PyException_SetTraceback( value, (PyObject *)traceback );
#endif

        throw PythonException(
            INCREASE_REFCOUNT( exception_type ),
            INCREASE_REFCOUNT( value ),
            INCREASE_REFCOUNT( traceback )
        );
    }
    else
    {
        PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name );

        PythonException to_throw;
        to_throw.setTraceback( INCREASE_REFCOUNT( traceback ) );

        throw to_throw;
    }
}
Exemple #23
0
static PyObject *
green_throw(PyGreenlet *self, PyObject *args)
{
	PyObject *typ = PyExc_GreenletExit;
	PyObject *val = NULL;
	PyObject *tb = NULL;

	if (!PyArg_ParseTuple(args, "|OOO:throw", &typ, &val, &tb))
	{
		return NULL;
	}

	/* First, check the traceback argument, replacing None, with NULL */
	if (tb == Py_None)
	{
		tb = NULL;
	}
	else if (tb != NULL && !PyTraceBack_Check(tb))
	{
		PyErr_SetString(
			PyExc_TypeError,
			"throw() third argument must be a traceback object");
		return NULL;
	}

	Py_INCREF(typ);
	Py_XINCREF(val);
	Py_XINCREF(tb);

	if (PyExceptionClass_Check(typ))
	{
		PyErr_NormalizeException(&typ, &val, &tb);
	}
	else if (PyExceptionInstance_Check(typ))
	{
		/* Raising an instance. The value should be a dummy. */
		if (val && val != Py_None)
		{
			PyErr_SetString(
				PyExc_TypeError,
				"instance exception may not have a separate value");
			goto failed_throw;
		}
		else
		{
			/* Normalize to raise <class>, <instance> */
			Py_XDECREF(val);
			val = typ;
			typ = PyExceptionInstance_Class(typ);
			Py_INCREF(typ);
		}
	}
	else
	{
		/* Not something you can raise. throw() fails. */
		PyErr_Format(
			PyExc_TypeError,
			"exceptions must be classes, or instances, not %s",
			Py_TYPE(typ)->tp_name);
		goto failed_throw;
	}

	return throw_greenlet(self, typ, val, tb);

 failed_throw:
	/* Didn't use our arguments, so restore their original refcounts */
	Py_DECREF(typ);
	Py_XDECREF(val);
	Py_XDECREF(tb);
	return NULL;
}
Exemple #24
0
static PyObject *Nuitka_Generator_throw( struct Nuitka_GeneratorObject *generator, PyObject *args )
{
    assert( generator->m_exception_type == NULL );
    assert( generator->m_exception_value == NULL );
    assert( generator->m_exception_tb == NULL );

    int res = PyArg_UnpackTuple( args, "throw", 1, 3, &generator->m_exception_type, &generator->m_exception_value, (PyObject **)&generator->m_exception_tb );

    if (unlikely( res == 0 ))
    {
        generator->m_exception_type = NULL;
        generator->m_exception_value = NULL;
        generator->m_exception_tb = NULL;

        return NULL;
    }

    if ( (PyObject *)generator->m_exception_tb == Py_None )
    {
        generator->m_exception_tb = NULL;
    }
    else if ( generator->m_exception_tb != NULL && !PyTraceBack_Check( generator->m_exception_tb ) )
    {
        generator->m_exception_type = NULL;
        generator->m_exception_value = NULL;
        generator->m_exception_tb = NULL;

        PyErr_Format( PyExc_TypeError, "throw() third argument must be a traceback object" );
        return NULL;
    }

    if ( PyExceptionClass_Check( generator->m_exception_type ))
    {
        Py_INCREF( generator->m_exception_type );
        Py_XINCREF( generator->m_exception_value );
        Py_XINCREF( generator->m_exception_tb );

        NORMALIZE_EXCEPTION( &generator->m_exception_type, &generator->m_exception_value, &generator->m_exception_tb );
    }
    else if ( PyExceptionInstance_Check( generator->m_exception_type ) )
    {
        if ( generator->m_exception_value && generator->m_exception_value != Py_None )
        {
            generator->m_exception_type = NULL;
            generator->m_exception_value = NULL;
            generator->m_exception_tb = NULL;

            PyErr_Format( PyExc_TypeError, "instance exception may not have a separate value" );
            return NULL;
        }
        generator->m_exception_value = generator->m_exception_type;
        Py_INCREF( generator->m_exception_value );
        generator->m_exception_type = PyExceptionInstance_Class( generator->m_exception_type );
        Py_INCREF( generator->m_exception_type );
        Py_XINCREF( generator->m_exception_tb );
    }
    else
    {
        PyErr_Format(
            PyExc_TypeError,
#if PYTHON_VERSION < 300
            "exceptions must be classes, or instances, not %s",
#else
            "exceptions must be classes or instances deriving from BaseException, not %s",
#endif
            Py_TYPE( generator->m_exception_type )->tp_name
        );

        generator->m_exception_type = NULL;
        generator->m_exception_value = NULL;
        generator->m_exception_tb = NULL;

        return NULL;
    }

    if ( ( generator->m_exception_tb != NULL ) && ( (PyObject *)generator->m_exception_tb != Py_None ) && ( !PyTraceBack_Check( generator->m_exception_tb ) ) )
    {
        PyErr_Format( PyExc_TypeError, "throw() third argument must be a traceback object" );
        return NULL;
    }

    if ( generator->m_status != status_Finished )
    {
        PyObject *result = Nuitka_Generator_send( generator, Py_None );

        return result;
    }
    else
    {
        RESTORE_ERROR_OCCURRED( generator->m_exception_type, generator->m_exception_value, generator->m_exception_tb );

        generator->m_exception_type = NULL;
        generator->m_exception_value = NULL;
        generator->m_exception_tb = NULL;

        return NULL;
    }
}