@@ -541,23 +541,28 @@ proxy_check_ref(PyObject *obj)
541541
542542/* If a parameter is a proxy, check that it is still "live" and wrap it,
543543 * replacing the original value with the raw object. Raises ReferenceError
544- * if the param is a dead proxy.
544+ * if the param is a dead proxy. Returns a new reference.
545545 */
546- #define UNWRAP (o ) \
547- if (PyWeakref_CheckProxy(o)) { \
548- o = _PyWeakref_GET_REF(o); \
549- if (!proxy_check_ref(o)) { \
550- return NULL; \
551- } \
552- } \
553- else { \
554- Py_INCREF(o); \
546+ static inline PyObject *
547+ proxy_unwrap (PyObject * obj )
548+ {
549+ if (PyWeakref_CheckProxy (obj )) {
550+ obj = _PyWeakref_GET_REF (obj );
551+ if (!proxy_check_ref (obj )) {
552+ return NULL ;
555553 }
554+ return obj ;
555+ }
556+ return Py_NewRef (obj );
557+ }
556558
557559#define WRAP_UNARY (method , generic ) \
558560 static PyObject * \
559561 method(PyObject *proxy) { \
560- UNWRAP(proxy); \
562+ proxy = proxy_unwrap(proxy); \
563+ if (proxy == NULL) { \
564+ return NULL; \
565+ } \
561566 PyObject* res = generic(proxy); \
562567 Py_DECREF(proxy); \
563568 return res; \
@@ -566,8 +571,15 @@ proxy_check_ref(PyObject *obj)
566571#define WRAP_BINARY (method , generic ) \
567572 static PyObject * \
568573 method(PyObject *x, PyObject *y) { \
569- UNWRAP(x); \
570- UNWRAP(y); \
574+ x = proxy_unwrap(x); \
575+ if (x == NULL) { \
576+ return NULL; \
577+ } \
578+ y = proxy_unwrap(y); \
579+ if (y == NULL) { \
580+ Py_DECREF(x); \
581+ return NULL; \
582+ } \
571583 PyObject* res = generic(x, y); \
572584 Py_DECREF(x); \
573585 Py_DECREF(y); \
@@ -580,10 +592,22 @@ proxy_check_ref(PyObject *obj)
580592#define WRAP_TERNARY (method , generic ) \
581593 static PyObject * \
582594 method(PyObject *proxy, PyObject *v, PyObject *w) { \
583- UNWRAP(proxy); \
584- UNWRAP(v); \
595+ proxy = proxy_unwrap(proxy); \
596+ if (proxy == NULL) { \
597+ return NULL; \
598+ } \
599+ v = proxy_unwrap(v); \
600+ if (v == NULL) { \
601+ Py_DECREF(proxy); \
602+ return NULL; \
603+ } \
585604 if (w != NULL) { \
586- UNWRAP(w); \
605+ w = proxy_unwrap(w); \
606+ if (w == NULL) { \
607+ Py_DECREF(proxy); \
608+ Py_DECREF(v); \
609+ return NULL; \
610+ } \
587611 } \
588612 PyObject* res = generic(proxy, v, w); \
589613 Py_DECREF(proxy); \
@@ -595,7 +619,10 @@ proxy_check_ref(PyObject *obj)
595619#define WRAP_METHOD (method , SPECIAL ) \
596620 static PyObject * \
597621 method(PyObject *proxy, PyObject *Py_UNUSED(ignored)) { \
598- UNWRAP(proxy); \
622+ proxy = proxy_unwrap(proxy); \
623+ if (proxy == NULL) { \
624+ return NULL; \
625+ } \
599626 PyObject* res = PyObject_CallMethodNoArgs(proxy, &_Py_ID(SPECIAL)); \
600627 Py_DECREF(proxy); \
601628 return res; \
@@ -643,8 +670,15 @@ proxy_setattr(PyObject *proxy, PyObject *name, PyObject *value)
643670static PyObject *
644671proxy_richcompare (PyObject * proxy , PyObject * v , int op )
645672{
646- UNWRAP (proxy );
647- UNWRAP (v );
673+ proxy = proxy_unwrap (proxy );
674+ if (proxy == NULL ) {
675+ return NULL ;
676+ }
677+ v = proxy_unwrap (v );
678+ if (v == NULL ) {
679+ Py_DECREF (proxy );
680+ return NULL ;
681+ }
648682 PyObject * res = PyObject_RichCompare (proxy , v , op );
649683 Py_DECREF (proxy );
650684 Py_DECREF (v );
0 commit comments