summaryrefslogtreecommitdiff
path: root/Objects/exceptions.c
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2013-11-19 22:33:10 +1000
committerNick Coghlan <ncoghlan@gmail.com>2013-11-19 22:33:10 +1000
commitf1de55fb334004c5e23d1adfe5d59957674f38a6 (patch)
tree9bb511393d52a7ffaa676b9c6cebc2ee50599016 /Objects/exceptions.c
parenta7261921811d6fc47ddfc9fe548c10a9f9f61b73 (diff)
downloadcpython-git-f1de55fb334004c5e23d1adfe5d59957674f38a6.tar.gz
Also chain codec exceptions that allow weakrefs
The zlib and hex codecs throw custom exception types with weakref support if the input type is valid, but the data fails validation. Make sure the exception chaining in the codec infrastructure can wrap those as well.
Diffstat (limited to 'Objects/exceptions.c')
-rw-r--r--Objects/exceptions.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 3476db02df..af40bc8fea 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -2630,16 +2630,27 @@ _PyErr_TrySetFromCause(const char *format, ...)
PyTypeObject *caught_type;
PyObject **dictptr;
PyObject *instance_args;
- Py_ssize_t num_args;
+ Py_ssize_t num_args, caught_type_size, base_exc_size;
PyObject *new_exc, *new_val, *new_tb;
va_list vargs;
+ int same_basic_size;
PyErr_Fetch(&exc, &val, &tb);
caught_type = (PyTypeObject *)exc;
- /* Ensure type info indicates no extra state is stored at the C level */
+ /* Ensure type info indicates no extra state is stored at the C level
+ * and that the type can be reinstantiated using PyErr_Format
+ */
+ caught_type_size = caught_type->tp_basicsize;
+ base_exc_size = _PyExc_BaseException.tp_basicsize;
+ same_basic_size = (
+ caught_type_size == base_exc_size ||
+ (PyType_SUPPORTS_WEAKREFS(caught_type) &&
+ (caught_type_size == base_exc_size + sizeof(PyObject *))
+ )
+ );
if (caught_type->tp_init != (initproc)BaseException_init ||
caught_type->tp_new != BaseException_new ||
- caught_type->tp_basicsize != _PyExc_BaseException.tp_basicsize ||
+ !same_basic_size ||
caught_type->tp_itemsize != _PyExc_BaseException.tp_itemsize) {
/* We can't be sure we can wrap this safely, since it may contain
* more state than just the exception type. Accordingly, we just