commit
e82725b22e
3 changed files with 132 additions and 55 deletions
|
|
@ -7,6 +7,32 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
||||||
Version 4.1.0 (in progress)
|
Version 4.1.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2021-05-17: adr26
|
||||||
|
[Python] #1985 Fix memory leaks:
|
||||||
|
|
||||||
|
1. Python object references were being incorrectly retained by
|
||||||
|
SwigPyClientData, causing swig_varlink_dealloc() never to run / free
|
||||||
|
memory. SwigPyClientData_New() / SwigPyClientData_Del() were updated
|
||||||
|
to fix the object reference counting, causing swig_varlink_dealloc()
|
||||||
|
to run and the memory swig_varlink owns to be freed.
|
||||||
|
|
||||||
|
2. SwigPyClientData itself was not freed by SwigPyClientData_Del(),
|
||||||
|
causing another heap leak. The required free() was added to
|
||||||
|
SwigPyClientData_Del()
|
||||||
|
|
||||||
|
3. Fix reference counting/leak of python cached type query
|
||||||
|
|
||||||
|
4. Fix reference counting/leak of SwigPyObject dict (-builtin)
|
||||||
|
|
||||||
|
5. Python object reference counting fixes for out-of-memory
|
||||||
|
scenarios were added to: SWIG_Python_RaiseOrModifyTypeError(),
|
||||||
|
SWIG_Python_AppendOutput(), SwigPyClientData_New(),
|
||||||
|
SwigPyObject_get___dict__() and SwigPyObject_format()
|
||||||
|
|
||||||
|
6. Add error handling for PyModule_AddObject() to
|
||||||
|
SWIG_Python_SetModule() (failure could be caused by OOM or a name
|
||||||
|
clash caused by malicious code)
|
||||||
|
|
||||||
2021-05-13: olly
|
2021-05-13: olly
|
||||||
[UFFI] #2009 Remove code for Common Lisp UFFI. We dropped support
|
[UFFI] #2009 Remove code for Common Lisp UFFI. We dropped support
|
||||||
for it in SWIG 4.0.0 and nobody has stepped forward to revive it in
|
for it in SWIG 4.0.0 and nobody has stepped forward to revive it in
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,12 @@ SWIG_Python_RaiseOrModifyTypeError(const char *message)
|
||||||
#else
|
#else
|
||||||
newvalue = PyString_FromFormat("%s\nAdditional information:\n%s", PyString_AsString(value), message);
|
newvalue = PyString_FromFormat("%s\nAdditional information:\n%s", PyString_AsString(value), message);
|
||||||
#endif
|
#endif
|
||||||
Py_XDECREF(value);
|
if (newvalue) {
|
||||||
PyErr_Restore(type, newvalue, traceback);
|
Py_XDECREF(value);
|
||||||
|
PyErr_Restore(type, newvalue, traceback);
|
||||||
|
} else {
|
||||||
|
PyErr_Restore(type, value, traceback);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Raise TypeError using given message */
|
/* Raise TypeError using given message */
|
||||||
PyErr_SetString(PyExc_TypeError, message);
|
PyErr_SetString(PyExc_TypeError, message);
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,12 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
|
||||||
if (!PyList_Check(result)) {
|
if (!PyList_Check(result)) {
|
||||||
PyObject *o2 = result;
|
PyObject *o2 = result;
|
||||||
result = PyList_New(1);
|
result = PyList_New(1);
|
||||||
PyList_SetItem(result, 0, o2);
|
if (result) {
|
||||||
|
PyList_SET_ITEM(result, 0, o2);
|
||||||
|
} else {
|
||||||
|
Py_DECREF(obj);
|
||||||
|
return o2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PyList_Append(result,obj);
|
PyList_Append(result,obj);
|
||||||
Py_DECREF(obj);
|
Py_DECREF(obj);
|
||||||
|
|
@ -279,18 +284,25 @@ SwigPyClientData_New(PyObject* obj)
|
||||||
/* the newraw method and newargs arguments used to create a new raw instance */
|
/* the newraw method and newargs arguments used to create a new raw instance */
|
||||||
if (PyClass_Check(obj)) {
|
if (PyClass_Check(obj)) {
|
||||||
data->newraw = 0;
|
data->newraw = 0;
|
||||||
data->newargs = obj;
|
|
||||||
Py_INCREF(obj);
|
Py_INCREF(obj);
|
||||||
|
data->newargs = obj;
|
||||||
} else {
|
} else {
|
||||||
data->newraw = PyObject_GetAttrString(data->klass, "__new__");
|
data->newraw = PyObject_GetAttrString(data->klass, "__new__");
|
||||||
if (data->newraw) {
|
if (data->newraw) {
|
||||||
Py_INCREF(data->newraw);
|
data->newargs = PyTuple_New(1);
|
||||||
data->newargs = PyTuple_New(1);
|
if (data->newargs) {
|
||||||
PyTuple_SetItem(data->newargs, 0, obj);
|
Py_INCREF(obj);
|
||||||
|
PyTuple_SET_ITEM(data->newargs, 0, obj);
|
||||||
|
} else {
|
||||||
|
Py_DECREF(data->newraw);
|
||||||
|
Py_DECREF(data->klass);
|
||||||
|
free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
data->newargs = obj;
|
Py_INCREF(obj);
|
||||||
|
data->newargs = obj;
|
||||||
}
|
}
|
||||||
Py_INCREF(data->newargs);
|
|
||||||
}
|
}
|
||||||
/* the destroy method, aka as the C++ delete method */
|
/* the destroy method, aka as the C++ delete method */
|
||||||
data->destroy = PyObject_GetAttrString(data->klass, "__swig_destroy__");
|
data->destroy = PyObject_GetAttrString(data->klass, "__swig_destroy__");
|
||||||
|
|
@ -299,10 +311,7 @@ SwigPyClientData_New(PyObject* obj)
|
||||||
data->destroy = 0;
|
data->destroy = 0;
|
||||||
}
|
}
|
||||||
if (data->destroy) {
|
if (data->destroy) {
|
||||||
int flags;
|
data->delargs = !(PyCFunction_GET_FLAGS(data->destroy) & METH_O);
|
||||||
Py_INCREF(data->destroy);
|
|
||||||
flags = PyCFunction_GET_FLAGS(data->destroy);
|
|
||||||
data->delargs = !(flags & (METH_O));
|
|
||||||
} else {
|
} else {
|
||||||
data->delargs = 0;
|
data->delargs = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -313,10 +322,13 @@ SwigPyClientData_New(PyObject* obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
SWIGRUNTIME void
|
SWIGRUNTIME void
|
||||||
SwigPyClientData_Del(SwigPyClientData *data) {
|
SwigPyClientData_Del(SwigPyClientData *data)
|
||||||
|
{
|
||||||
|
Py_XDECREF(data->klass);
|
||||||
Py_XDECREF(data->newraw);
|
Py_XDECREF(data->newraw);
|
||||||
Py_XDECREF(data->newargs);
|
Py_XDECREF(data->newargs);
|
||||||
Py_XDECREF(data->destroy);
|
Py_XDECREF(data->destroy);
|
||||||
|
free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =============== SwigPyObject =====================*/
|
/* =============== SwigPyObject =====================*/
|
||||||
|
|
@ -343,7 +355,7 @@ SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
|
||||||
if (!sobj->dict)
|
if (!sobj->dict)
|
||||||
sobj->dict = PyDict_New();
|
sobj->dict = PyDict_New();
|
||||||
|
|
||||||
Py_INCREF(sobj->dict);
|
Py_XINCREF(sobj->dict);
|
||||||
return sobj->dict;
|
return sobj->dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -361,18 +373,21 @@ SwigPyObject_format(const char* fmt, SwigPyObject *v)
|
||||||
PyObject *res = NULL;
|
PyObject *res = NULL;
|
||||||
PyObject *args = PyTuple_New(1);
|
PyObject *args = PyTuple_New(1);
|
||||||
if (args) {
|
if (args) {
|
||||||
if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) {
|
PyObject *val = SwigPyObject_long(v);
|
||||||
PyObject *ofmt = SWIG_Python_str_FromChar(fmt);
|
if (val) {
|
||||||
|
PyObject *ofmt;
|
||||||
|
PyTuple_SET_ITEM(args, 0, val);
|
||||||
|
ofmt = SWIG_Python_str_FromChar(fmt);
|
||||||
if (ofmt) {
|
if (ofmt) {
|
||||||
#if PY_VERSION_HEX >= 0x03000000
|
#if PY_VERSION_HEX >= 0x03000000
|
||||||
res = PyUnicode_Format(ofmt,args);
|
res = PyUnicode_Format(ofmt,args);
|
||||||
#else
|
#else
|
||||||
res = PyString_Format(ofmt,args);
|
res = PyString_Format(ofmt,args);
|
||||||
#endif
|
#endif
|
||||||
Py_DECREF(ofmt);
|
Py_DECREF(ofmt);
|
||||||
}
|
}
|
||||||
Py_DECREF(args);
|
|
||||||
}
|
}
|
||||||
|
Py_DECREF(args);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -394,18 +409,23 @@ SwigPyObject_repr(SwigPyObject *v)
|
||||||
{
|
{
|
||||||
const char *name = SWIG_TypePrettyName(v->ty);
|
const char *name = SWIG_TypePrettyName(v->ty);
|
||||||
PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
|
PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
|
||||||
if (v->next) {
|
if (repr && v->next) {
|
||||||
PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
|
PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
|
||||||
|
if (nrep) {
|
||||||
# if PY_VERSION_HEX >= 0x03000000
|
# if PY_VERSION_HEX >= 0x03000000
|
||||||
PyObject *joined = PyUnicode_Concat(repr, nrep);
|
PyObject *joined = PyUnicode_Concat(repr, nrep);
|
||||||
Py_DecRef(repr);
|
Py_DecRef(repr);
|
||||||
Py_DecRef(nrep);
|
Py_DecRef(nrep);
|
||||||
repr = joined;
|
repr = joined;
|
||||||
# else
|
# else
|
||||||
PyString_ConcatAndDel(&repr,nrep);
|
PyString_ConcatAndDel(&repr,nrep);
|
||||||
# endif
|
# endif
|
||||||
|
} else {
|
||||||
|
Py_DecRef(repr);
|
||||||
|
repr = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return repr;
|
return repr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need a version taking two PyObject* parameters so it's a valid
|
/* We need a version taking two PyObject* parameters so it's a valid
|
||||||
|
|
@ -501,8 +521,12 @@ SwigPyObject_dealloc(PyObject *v)
|
||||||
if (data->delargs) {
|
if (data->delargs) {
|
||||||
/* we need to create a temporary object to carry the destroy operation */
|
/* we need to create a temporary object to carry the destroy operation */
|
||||||
PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
|
PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
|
||||||
res = SWIG_Python_CallFunctor(destroy, tmp);
|
if (tmp) {
|
||||||
Py_DECREF(tmp);
|
res = SWIG_Python_CallFunctor(destroy, tmp);
|
||||||
|
} else {
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
Py_XDECREF(tmp);
|
||||||
} else {
|
} else {
|
||||||
PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
|
PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
|
||||||
PyObject *mself = PyCFunction_GET_SELF(destroy);
|
PyObject *mself = PyCFunction_GET_SELF(destroy);
|
||||||
|
|
@ -523,6 +547,9 @@ SwigPyObject_dealloc(PyObject *v)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Py_XDECREF(next);
|
Py_XDECREF(next);
|
||||||
|
#ifdef SWIGPYTHON_BUILTIN
|
||||||
|
Py_XDECREF(sobj->dict);
|
||||||
|
#endif
|
||||||
PyObject_DEL(v);
|
PyObject_DEL(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -578,9 +605,9 @@ SwigPyObject_own(PyObject *v, PyObject *args)
|
||||||
PyObject *obj = PyBool_FromLong(sobj->own);
|
PyObject *obj = PyBool_FromLong(sobj->own);
|
||||||
if (val) {
|
if (val) {
|
||||||
if (PyObject_IsTrue(val)) {
|
if (PyObject_IsTrue(val)) {
|
||||||
SwigPyObject_acquire(v,args);
|
Py_DECREF(SwigPyObject_acquire(v,args));
|
||||||
} else {
|
} else {
|
||||||
SwigPyObject_disown(v,args);
|
Py_DECREF(SwigPyObject_disown(v,args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
|
@ -725,7 +752,7 @@ SwigPyObject_TypeOnce(void) {
|
||||||
};
|
};
|
||||||
swigpyobject_type = tmp;
|
swigpyobject_type = tmp;
|
||||||
type_init = 1;
|
type_init = 1;
|
||||||
if (PyType_Ready(&swigpyobject_type) < 0)
|
if (PyType_Ready(&swigpyobject_type) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return &swigpyobject_type;
|
return &swigpyobject_type;
|
||||||
|
|
@ -740,6 +767,9 @@ SwigPyObject_New(void *ptr, swig_type_info *ty, int own)
|
||||||
sobj->ty = ty;
|
sobj->ty = ty;
|
||||||
sobj->own = own;
|
sobj->own = own;
|
||||||
sobj->next = 0;
|
sobj->next = 0;
|
||||||
|
#ifdef SWIGPYTHON_BUILTIN
|
||||||
|
sobj->dict = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return (PyObject *)sobj;
|
return (PyObject *)sobj;
|
||||||
}
|
}
|
||||||
|
|
@ -892,7 +922,7 @@ SwigPyPacked_TypeOnce(void) {
|
||||||
};
|
};
|
||||||
swigpypacked_type = tmp;
|
swigpypacked_type = tmp;
|
||||||
type_init = 1;
|
type_init = 1;
|
||||||
if (PyType_Ready(&swigpypacked_type) < 0)
|
if (PyType_Ready(&swigpypacked_type) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return &swigpypacked_type;
|
return &swigpypacked_type;
|
||||||
|
|
@ -1200,12 +1230,17 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
|
||||||
#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
|
#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
|
||||||
PyObject **dictptr = _PyObject_GetDictPtr(inst);
|
PyObject **dictptr = _PyObject_GetDictPtr(inst);
|
||||||
if (dictptr != NULL) {
|
if (dictptr != NULL) {
|
||||||
PyObject *dict = *dictptr;
|
PyObject *dict = *dictptr;
|
||||||
if (dict == NULL) {
|
if (dict == NULL) {
|
||||||
dict = PyDict_New();
|
dict = PyDict_New();
|
||||||
*dictptr = dict;
|
*dictptr = dict;
|
||||||
PyDict_SetItem(dict, SWIG_This(), swig_this);
|
}
|
||||||
}
|
if (dict) {
|
||||||
|
PyDict_SetItem(dict, SWIG_This(), swig_this);
|
||||||
|
} else{
|
||||||
|
Py_DECREF(inst);
|
||||||
|
inst = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (PyObject_SetAttr(inst, SWIG_This(), swig_this) == -1) {
|
if (PyObject_SetAttr(inst, SWIG_This(), swig_this) == -1) {
|
||||||
|
|
@ -1256,7 +1291,11 @@ SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
|
||||||
dict = PyDict_New();
|
dict = PyDict_New();
|
||||||
*dictptr = dict;
|
*dictptr = dict;
|
||||||
}
|
}
|
||||||
return PyDict_SetItem(dict, SWIG_This(), swig_this);
|
if (dict) {
|
||||||
|
return PyDict_SetItem(dict, SWIG_This(), swig_this);
|
||||||
|
} else{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return PyObject_SetAttr(inst, SWIG_This(), swig_this);
|
return PyObject_SetAttr(inst, SWIG_This(), swig_this);
|
||||||
|
|
@ -1271,7 +1310,7 @@ SWIG_Python_InitShadowInstance(PyObject *args) {
|
||||||
} else {
|
} else {
|
||||||
SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
|
SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
|
||||||
if (sthis) {
|
if (sthis) {
|
||||||
SwigPyObject_append((PyObject*) sthis, obj[1]);
|
Py_DECREF(SwigPyObject_append((PyObject*) sthis, obj[1]));
|
||||||
} else {
|
} else {
|
||||||
if (SWIG_Python_SetSwigThis(obj[0], obj[1]) != 0)
|
if (SWIG_Python_SetSwigThis(obj[0], obj[1]) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1310,7 +1349,9 @@ SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int f
|
||||||
} else {
|
} else {
|
||||||
newobj = PyObject_New(SwigPyObject, clientdata->pytype);
|
newobj = PyObject_New(SwigPyObject, clientdata->pytype);
|
||||||
#ifdef SWIGPYTHON_BUILTIN
|
#ifdef SWIGPYTHON_BUILTIN
|
||||||
newobj->dict = 0;
|
if (newobj) {
|
||||||
|
newobj->dict = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (newobj) {
|
if (newobj) {
|
||||||
|
|
@ -1349,6 +1390,13 @@ SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) {
|
||||||
void *SWIG_ReturnGlobalTypeList(void *);
|
void *SWIG_ReturnGlobalTypeList(void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* The python cached type query */
|
||||||
|
SWIGRUNTIME PyObject *
|
||||||
|
SWIG_Python_TypeCache(void) {
|
||||||
|
static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New();
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
SWIGRUNTIME swig_module_info *
|
SWIGRUNTIME swig_module_info *
|
||||||
SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
|
SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
|
||||||
static void *type_pointer = (void *)0;
|
static void *type_pointer = (void *)0;
|
||||||
|
|
@ -1377,11 +1425,13 @@ SWIG_Python_DestroyModule(PyObject *obj)
|
||||||
swig_type_info *ty = types[i];
|
swig_type_info *ty = types[i];
|
||||||
if (ty->owndata) {
|
if (ty->owndata) {
|
||||||
SwigPyClientData *data = (SwigPyClientData *) ty->clientdata;
|
SwigPyClientData *data = (SwigPyClientData *) ty->clientdata;
|
||||||
|
ty->clientdata = 0;
|
||||||
if (data) SwigPyClientData_Del(data);
|
if (data) SwigPyClientData_Del(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Py_DECREF(SWIG_This());
|
Py_DECREF(SWIG_This());
|
||||||
Swig_This_global = NULL;
|
Swig_This_global = NULL;
|
||||||
|
Py_DECREF(SWIG_Python_TypeCache());
|
||||||
}
|
}
|
||||||
|
|
||||||
SWIGRUNTIME void
|
SWIGRUNTIME void
|
||||||
|
|
@ -1395,19 +1445,14 @@ SWIG_Python_SetModule(swig_module_info *swig_module) {
|
||||||
#endif
|
#endif
|
||||||
PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
|
PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
|
||||||
if (pointer && module) {
|
if (pointer && module) {
|
||||||
PyModule_AddObject(module, "type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer);
|
if (PyModule_AddObject(module, "type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer) != 0) {
|
||||||
|
Py_DECREF(pointer);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Py_XDECREF(pointer);
|
Py_XDECREF(pointer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The python cached type query */
|
|
||||||
SWIGRUNTIME PyObject *
|
|
||||||
SWIG_Python_TypeCache(void) {
|
|
||||||
static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New();
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
SWIGRUNTIME swig_type_info *
|
SWIGRUNTIME swig_type_info *
|
||||||
SWIG_Python_TypeQuery(const char *type)
|
SWIG_Python_TypeQuery(const char *type)
|
||||||
{
|
{
|
||||||
|
|
@ -1422,8 +1467,10 @@ SWIG_Python_TypeQuery(const char *type)
|
||||||
descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
|
descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
|
||||||
if (descriptor) {
|
if (descriptor) {
|
||||||
obj = PyCapsule_New((void*) descriptor, NULL, NULL);
|
obj = PyCapsule_New((void*) descriptor, NULL, NULL);
|
||||||
PyDict_SetItem(cache, key, obj);
|
if (obj) {
|
||||||
Py_DECREF(obj);
|
PyDict_SetItem(cache, key, obj);
|
||||||
|
Py_DECREF(obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Py_DECREF(key);
|
Py_DECREF(key);
|
||||||
|
|
@ -1566,7 +1613,7 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tp->tp_dict) {
|
if (!tp->tp_dict) {
|
||||||
if (PyType_Ready(tp) < 0)
|
if (PyType_Ready(tp) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1581,7 +1628,7 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
|
||||||
} else {
|
} else {
|
||||||
encoded_name = PyUnicode_AsUTF8String(name);
|
encoded_name = PyUnicode_AsUTF8String(name);
|
||||||
if (!encoded_name)
|
if (!encoded_name)
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
|
PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
|
||||||
Py_DECREF(encoded_name);
|
Py_DECREF(encoded_name);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue