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.
This commit is contained in:
parent
a5343ccd28
commit
73006d0237
|
@ -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); \
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue