summaryrefslogtreecommitdiffstats
path: root/Objects/weakrefobject.c
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2001-10-18 18:04:18 (GMT)
committerFred Drake <fdrake@acm.org>2001-10-18 18:04:18 (GMT)
commit73006d02374e785c660f15bad0aabcf197d97ce8 (patch)
tree844d1bd2f69a4890ea70bca54ac9fcb2cad53a03 /Objects/weakrefobject.c
parenta5343ccd28245d96feb21d1457802b97a76aa210 (diff)
downloadcpython-73006d02374e785c660f15bad0aabcf197d97ce8.zip
cpython-73006d02374e785c660f15bad0aabcf197d97ce8.tar.gz
cpython-73006d02374e785c660f15bad0aabcf197d97ce8.tar.bz2
When weakref proxies are involved in binary & ternary slot operations,
the left-hand operand may not be the proxy in all cases. If it isn't, we end up doing two things: a) unwrapping something that isn't a PyWeakReference (later resulting in a core dump) and b) passing a proxy as the right-hand operand anyway, even though that can't be handled by the actual handler (maybe eventually causing a core dump). This is fixed by always unwrapping all the proxies involved before passing anything to the actual handler.
Diffstat (limited to 'Objects/weakrefobject.c')
-rw-r--r--Objects/weakrefobject.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index 56ecfb3..886d874 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -207,31 +207,44 @@ proxy_checkref(PyWeakReference *proxy)
}
+/* If a parameter is a proxy, check that it is still "live" and wrap it,
+ * replacing the original value with the raw object. Raises ReferenceError
+ * if the param is a dead proxy.
+ */
+#define UNWRAP(o) \
+ if (PyWeakref_CheckProxy(o)) { \
+ if (!proxy_checkref((PyWeakReference *)o)) \
+ return NULL; \
+ o = PyWeakref_GET_OBJECT(o); \
+ }
+
#define WRAP_UNARY(method, generic) \
static PyObject * \
- method(PyWeakReference *proxy) { \
- if (!proxy_checkref(proxy)) { \
- return NULL; \
- } \
- return generic(PyWeakref_GET_OBJECT(proxy)); \
+ method(PyObject *proxy) { \
+ UNWRAP(proxy); \
+ return generic(proxy); \
}
#define WRAP_BINARY(method, generic) \
static PyObject * \
- method(PyWeakReference *proxy, PyObject *v) { \
- if (!proxy_checkref(proxy)) { \
- return NULL; \
- } \
- return generic(PyWeakref_GET_OBJECT(proxy), v); \
+ method(PyObject *x, PyObject *y) { \
+ UNWRAP(x); \
+ UNWRAP(y); \
+ return generic(x, y); \
}
+/* Note that the second and third args need to be checked for NULL since
+ * (at least) the tp_call slot can receive NULL for either of those args.
+ */
#define WRAP_TERNARY(method, generic) \
static PyObject * \
- method(PyWeakReference *proxy, PyObject *v, PyObject *w) { \
- if (!proxy_checkref(proxy)) { \
- return NULL; \
- } \
- return generic(PyWeakref_GET_OBJECT(proxy), v, w); \
+ method(PyObject *proxy, PyObject *v, PyObject *w) { \
+ UNWRAP(proxy); \
+ if (v != NULL) \
+ UNWRAP(v); \
+ if (w != NULL) \
+ UNWRAP(w); \
+ return generic(proxy, v, w); \
}