diff options
author | Benjamin Peterson <benjamin@python.org> | 2008-07-31 01:47:08 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2008-07-31 01:47:08 (GMT) |
commit | 69c88f74a377380eb34e1040f320039e3ab4d014 (patch) | |
tree | 5491fe578bbf73d6a23bffffb356b07a41a5abab | |
parent | ebaf75dc0bd7cce14196daedfd8fe2b88726572b (diff) | |
download | cpython-69c88f74a377380eb34e1040f320039e3ab4d014.zip cpython-69c88f74a377380eb34e1040f320039e3ab4d014.tar.gz cpython-69c88f74a377380eb34e1040f320039e3ab4d014.tar.bz2 |
Merged revisions 65320 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r65320 | amaury.forgeotdarc | 2008-07-30 19:42:16 -0500 (Wed, 30 Jul 2008) | 3 lines
#2542: now that issubclass() may call arbitrary code,
make sure that PyErr_ExceptionMatches returns 0 when an exception occurs there.
........
-rw-r--r-- | Lib/test/test_exceptions.py | 35 | ||||
-rw-r--r-- | Python/errors.c | 15 |
2 files changed, 45 insertions, 5 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index aa77292..2b248e1 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -6,12 +6,20 @@ import unittest import pickle import weakref -from test.support import TESTFN, unlink, run_unittest +from test.support import TESTFN, unlink, run_unittest, captured_output # XXX This is not really enough, each *operation* should be tested! class ExceptionTests(unittest.TestCase): + def test00(self): + try: + sys.exit(ValueError('aaa')) + except SystemExit: + pass + finally: + pass + def raise_catch(self, exc, excname): try: raise exc("spam") @@ -404,7 +412,6 @@ class ExceptionTests(unittest.TestCase): def testExceptionCleanupNames(self): # Make sure the local variable bound to the exception instance by # an "except" statement is only visible inside the except block. - try: raise Exception() except Exception as e: @@ -565,6 +572,30 @@ class ExceptionTests(unittest.TestCase): pass self.assertEquals(e, (None, None, None)) + def test_badisinstance(self): + # Bug #2542: if issubclass(e, MyException) raises an exception, + # it should be ignored + class Meta(type): + def __subclasscheck__(cls, subclass): + raise ValueError() + class MyException(Exception, metaclass=Meta): + pass + + with captured_output("stderr") as stderr: + try: + raise KeyError() + except MyException as e: + self.fail("exception should not be a MyException") + except KeyError: + pass + except: + self.fail("Should have raised TypeError") + else: + self.fail("Should have raised TypeError") + self.assertEqual(stderr.getvalue(), + "Exception ValueError: ValueError() " + "in <class 'KeyError'> ignored\n") + def test_main(): run_unittest(ExceptionTests) diff --git a/Python/errors.c b/Python/errors.c index 3b86c48..a06ec02 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -157,9 +157,18 @@ PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc) 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); + int res = 0; + PyObject *exception, *value, *tb; + PyErr_Fetch(&exception, &value, &tb); + res = PyObject_IsSubclass(err, exc); + /* This function must not fail, so print the error here */ + if (res == -1) { + PyErr_WriteUnraisable(err); + /* issubclass did not succeed */ + res = 0; + } + PyErr_Restore(exception, value, tb); + return res; } return err == exc; |