diff -Nru sip4-4.19.7+dfsg/debian/changelog sip4-4.19.7+dfsg/debian/changelog --- sip4-4.19.7+dfsg/debian/changelog 2018-01-25 09:41:02.000000000 +0000 +++ sip4-4.19.7+dfsg/debian/changelog 2020-03-02 17:04:07.000000000 +0000 @@ -1,3 +1,11 @@ +sip4 (4.19.7+dfsg-1ubuntu0.1) bionic; urgency=medium + + * Fixed issues with C/C++ member variable getters and setters. This + restores the keeping of a reference to the containing object in the + instance of a contained class (LP: #1861601). + + -- Dmitry Shachnev Mon, 02 Mar 2020 20:04:07 +0300 + sip4 (4.19.7+dfsg-1) unstable; urgency=medium * New upstream bugfix release. diff -Nru sip4-4.19.7+dfsg/debian/control sip4-4.19.7+dfsg/debian/control --- sip4-4.19.7+dfsg/debian/control 2018-01-25 09:41:02.000000000 +0000 +++ sip4-4.19.7+dfsg/debian/control 2020-02-25 12:19:25.000000000 +0000 @@ -1,7 +1,8 @@ Source: sip4 Section: devel Priority: optional -Maintainer: Debian Python Modules Team +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Python Modules Team Uploaders: Torsten Marek , Scott Kitterman , Dmitry Shachnev diff -Nru sip4-4.19.7+dfsg/debian/patches/keep_reference.diff sip4-4.19.7+dfsg/debian/patches/keep_reference.diff --- sip4-4.19.7+dfsg/debian/patches/keep_reference.diff 1970-01-01 00:00:00.000000000 +0000 +++ sip4-4.19.7+dfsg/debian/patches/keep_reference.diff 2020-03-02 17:03:59.000000000 +0000 @@ -0,0 +1,197 @@ +Description: fixed issues with C/C++ member variable getters and setters +Origin: upstream, commits: + https://www.riverbankcomputing.com/hg/sip/rev/137b9be794a1 + https://www.riverbankcomputing.com/hg/sip/rev/6a057b2d8537 + https://www.riverbankcomputing.com/hg/sip/rev/699facc95914 + https://www.riverbankcomputing.com/hg/sip/rev/82ec38dc0e63 +Last-Update: 2020-03-02 + +--- a/sipgen/gencode.c ++++ b/sipgen/gencode.c +@@ -4886,10 +4886,7 @@ static void generateVariableGetter(iface + { + argType atype = vd->type.atype; + const char *first_arg, *second_arg, *last_arg; +- int needsNew; +- +- if (keepPyReference(&vd->type)) +- vd->type.key = vd->module->next_key--; ++ int needsNew, var_key, self_key; + + if (generating_c || !isStaticVar(vd)) + first_arg = "sipSelf"; +@@ -4900,7 +4897,32 @@ static void generateVariableGetter(iface + + needsNew = ((atype == class_type || atype == mapped_type) && vd->type.nrderefs == 0 && isConstArg(&vd->type)); + +- second_arg = (generating_c || (vd->type.key < 0 && !isStaticVar(vd))) ? "sipPySelf" : ""; ++ /* ++ * If the variable is itself a non-const instance of a wrapped class then ++ * two things must happen. Firstly, the getter must return the same Python ++ * object each time - it must not re-wrap the the instance. This is ++ * because the Python object can contain important state information that ++ * must not be lost (specifically references to other Python objects that ++ * it owns). Therefore the Python object wrapping the containing class ++ * must cache a reference to the Python object wrapping the variable. ++ * Secondly, the Python object wrapping the containing class must not be ++ * garbage collected before the Python object wrapping the variable is ++ * (because the latter references memory, ie. the variable itself, that is ++ * managed by the former). Therefore the Python object wrapping the ++ * variable must keep a reference to the Python object wrapping the ++ * containing class (but only if the latter is non-static). ++ */ ++ var_key = self_key = 0; ++ ++ if (atype == class_type && vd->type.nrderefs == 0 && !isConstArg(&vd->type)) ++ { ++ var_key = vd->type.u.cd->iff->module->next_key--; ++ ++ if (!isStaticVar(vd)) ++ self_key = vd->module->next_key--; ++ } ++ ++ second_arg = (generating_c || var_key < 0 ) ? "sipPySelf" : ""; + + prcode(fp, + "\n" +@@ -4923,7 +4945,7 @@ static void generateVariableGetter(iface + " PyObject *sipPy;\n" + ); + } +- else if (vd->type.key < 0) ++ else if (var_key < 0) + { + if (isStaticVar(vd)) + prcode(fp, +@@ -4976,10 +4998,10 @@ static void generateVariableGetter(iface + return; + } + +- if (vd->type.key < 0) ++ /* Get any previously wrapped cached object. */ ++ if (var_key < 0) + { + if (isStaticVar(vd)) +- { + prcode(fp, + " if (sipPy)\n" + " {\n" +@@ -4988,16 +5010,14 @@ static void generateVariableGetter(iface + " }\n" + "\n" + ); +- } + else +- { + prcode(fp, + " sipPy = sipGetReference(sipPySelf, %d);\n" ++"\n" + " if (sipPy)\n" + " return sipPy;\n" + "\n" +- , vd->type.key); +- } ++ , self_key); + } + + if (needsNew) +@@ -5037,7 +5057,7 @@ static void generateVariableGetter(iface + iff = vd->type.u.cd->iff; + + prcode(fp, +-" %s sipConvertFrom%sType(", (vd->type.key < 0 ? "sipPy =" : "return"), (needsNew ? "New" : "")); ++" %s sipConvertFrom%sType(", (var_key < 0 ? "sipPy =" : "return"), (needsNew ? "New" : "")); + + if (isConstArg(&vd->type)) + prcode(fp, "const_cast<%b *>(sipVal)", &vd->type); +@@ -5047,18 +5067,26 @@ static void generateVariableGetter(iface + prcode(fp, ", sipType_%C, NULL);\n" + , iff->fqcname); + +- if (vd->type.key < 0) ++ if (var_key < 0) + { ++ prcode(fp, ++"\n" ++" if (sipPy)\n" ++" {\n" ++" sipKeepReference(sipPy, %d, sipPySelf);\n" ++ , var_key); ++ + if (isStaticVar(vd)) + prcode(fp, +-" Py_XINCREF(sipPy);\n" ++" Py_INCREF(sipPy);\n" + ); + else + prcode(fp, +-" sipKeepReference(sipPySelf, %d, sipPy);\n" +- , vd->type.key); ++" sipKeepReference(sipPySelf, %d, sipPy);\n" ++ , self_key); + + prcode(fp, ++" }\n" + "\n" + " return sipPy;\n" + ); +@@ -5311,14 +5339,20 @@ static void generateVariableSetter(iface + argType atype = vd->type.atype; + const char *first_arg, *last_arg, *error_test; + char *deref; +- int might_be_temp, need_py, need_cpp; ++ int might_be_temp, keep, need_py, need_cpp; ++ ++ /* ++ * We need to keep a reference to the original Python object if it ++ * providing the memory that the C/C++ variable is pointing to. ++ */ ++ keep = keepPyReference(&vd->type); + + if (generating_c || !isStaticVar(vd)) + first_arg = "sipSelf"; + else + first_arg = ""; + +- if (generating_c || (!isStaticVar(vd) && vd->type.key < 0)) ++ if (generating_c || (!isStaticVar(vd) && keep)) + last_arg = "sipPySelf"; + else + last_arg = ""; +@@ -5478,7 +5512,7 @@ static void generateVariableSetter(iface + , &vd->type); + + /* Generate the code to keep the object alive while we use its data. */ +- if (vd->type.key < 0) ++ if (keep) + { + if (isStaticVar(vd)) + { +@@ -5496,7 +5530,7 @@ static void generateVariableSetter(iface + prcode(fp, + "\n" + " sipKeepReference(sipPySelf, %d, sipPy);\n" +- , vd->type.key); ++ , scope->module->next_key--); + } + } + +@@ -5647,7 +5681,7 @@ static int generateObjToCppConversion(ar + else if (isConstArg(ad)) + rhs = "sipBytes_AsString(sipPy)"; + else +- rhs = "(const *)sipBytes_AsString(sipPy)"; ++ rhs = "(char *)sipBytes_AsString(sipPy)"; + break; + + case wstring_type: +--- a/siplib/siplib.c.in ++++ b/siplib/siplib.c.in +@@ -9152,6 +9152,7 @@ static PyObject *sip_api_get_reference(P + return NULL; + + obj = PyDict_GetItem(dict, key_obj); ++ Py_DECREF(key_obj); + Py_XINCREF(obj); + + return obj; diff -Nru sip4-4.19.7+dfsg/debian/patches/series sip4-4.19.7+dfsg/debian/patches/series --- sip4-4.19.7+dfsg/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ sip4-4.19.7+dfsg/debian/patches/series 2020-02-25 12:15:45.000000000 +0000 @@ -0,0 +1 @@ +keep_reference.diff