diff options
author | Fred Drake <fdrake@acm.org> | 2001-10-18 18:04:18 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2001-10-18 18:04:18 (GMT) |
commit | 73006d02374e785c660f15bad0aabcf197d97ce8 (patch) | |
tree | 844d1bd2f69a4890ea70bca54ac9fcb2cad53a03 /Objects/weakrefobject.c | |
parent | a5343ccd28245d96feb21d1457802b97a76aa210 (diff) | |
download | cpython-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.c | 43 |
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); \ } |