Fix the memory leak related to Python 3 unicode and char * conversion.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11160 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Haoyu Bai 2009-03-19 15:26:57 +00:00
commit a863d31e81
6 changed files with 67 additions and 10 deletions

View file

@ -1,6 +1,21 @@
Version 1.3.39 (in progress) Version 1.3.39 (in progress)
============================ ============================
2009-03-19: bhy
[Python] Fix the memory leak related to Python 3 unicode and C char* conversion,
which can be shown in the following example before this fix:
from li_cstring import *
i=0
while True:
i += 1
n = str(i)*10
test3(n)
This fix affected SWIG_AsCharPtrAndSize() so you cannot call this function with
a null alloc and non-null cptr argument in Python 3, otherwise a runtime error
will be raised.
2009-03-18: wsfulton 2009-03-18: wsfulton
[C#] std::vector<T> wrapper improvements for .NET 2 and also providing the [C#] std::vector<T> wrapper improvements for .NET 2 and also providing the
necessary machinery to use the std::vector<T> wrappers with more advanced features such necessary machinery to use the std::vector<T> wrappers with more advanced features such

View file

@ -55,11 +55,13 @@ SWIG_Python_AddErrorMsg(const char* mesg)
if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback);
if (value) { if (value) {
char *tmp;
PyObject *old_str = PyObject_Str(value); PyObject *old_str = PyObject_Str(value);
PyErr_Clear(); PyErr_Clear();
Py_XINCREF(type); Py_XINCREF(type);
PyErr_Format(type, "%s %s", SWIG_Python_str_AsChar(old_str), mesg); PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg);
SWIG_Python_str_DelForPy3(tmp);
Py_DECREF(old_str); Py_DECREF(old_str);
Py_DECREF(value); Py_DECREF(value);
} else { } else {

View file

@ -21,17 +21,35 @@
# define SWIG_Python_str_FromFormat PyString_FromFormat # define SWIG_Python_str_FromFormat PyString_FromFormat
#endif #endif
/* Warning: This function will allocate a new string in Python 3,
* so please call SWIG_Python_str_DelForPy3(x) to free the space.
*/
SWIGINTERN char* SWIGINTERN char*
SWIG_Python_str_AsChar(PyObject *str) SWIG_Python_str_AsChar(PyObject *str)
{ {
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
char *cstr;
char *newstr;
int len;
str = PyUnicode_AsUTF8String(str); str = PyUnicode_AsUTF8String(str);
return PyBytes_AsString(str); PyBytes_AsStringAndSize(str, &cstr, &len);
newstr = (char *) malloc(len+1);
memcpy(newstr, cstr, len+1);
Py_XDECREF(str);
return newstr;
#else #else
return PyString_AsString(str); return PyString_AsString(str);
#endif #endif
} }
#if PY_VERSION_HEX >= 0x03000000
# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) )
#else
# define SWIG_Python_str_DelForPy3(x)
#endif
SWIGINTERN PyObject* SWIGINTERN PyObject*
SWIG_Python_str_FromChar(const char *c) SWIG_Python_str_FromChar(const char *c)
{ {

View file

@ -80,9 +80,11 @@ swig_varlink_str(swig_varlinkobject *v) {
SWIGINTERN int SWIGINTERN int
swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) {
char *tmp;
PyObject *str = swig_varlink_str(v); PyObject *str = swig_varlink_str(v);
fprintf(fp,"Swig global variables "); fprintf(fp,"Swig global variables ");
fprintf(fp,"%s\n", SWIG_Python_str_AsChar(str)); fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str));
SWIG_Python_str_DelForPy3(tmp);
Py_DECREF(str); Py_DECREF(str);
return 0; return 0;
} }

View file

@ -407,13 +407,16 @@ SwigPyObject_repr(SwigPyObject *v, PyObject *args)
SWIGRUNTIME int SWIGRUNTIME int
SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
{ {
char *str;
#ifdef METH_NOARGS #ifdef METH_NOARGS
PyObject *repr = SwigPyObject_repr(v); PyObject *repr = SwigPyObject_repr(v);
#else #else
PyObject *repr = SwigPyObject_repr(v, NULL); PyObject *repr = SwigPyObject_repr(v, NULL);
#endif #endif
if (repr) { if (repr) {
fputs(SWIG_Python_str_AsChar(repr), fp); str = SWIG_Python_str_AsChar(repr);
fputs(str, fp);
SWIG_Python_str_DelForPy3(str);
Py_DECREF(repr); Py_DECREF(repr);
return 0; return 0;
} else { } else {
@ -1474,21 +1477,23 @@ SWIG_Python_TypeQuery(const char *type)
SWIGRUNTIME int SWIGRUNTIME int
SWIG_Python_AddErrMesg(const char* mesg, int infront) SWIG_Python_AddErrMesg(const char* mesg, int infront)
{ {
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
PyObject *type = 0; PyObject *type = 0;
PyObject *value = 0; PyObject *value = 0;
PyObject *traceback = 0; PyObject *traceback = 0;
PyErr_Fetch(&type, &value, &traceback); PyErr_Fetch(&type, &value, &traceback);
if (value) { if (value) {
char *tmp;
PyObject *old_str = PyObject_Str(value); PyObject *old_str = PyObject_Str(value);
Py_XINCREF(type); Py_XINCREF(type);
PyErr_Clear(); PyErr_Clear();
if (infront) { if (infront) {
PyErr_Format(type, "%s %s", mesg, SWIG_Python_str_AsChar(old_str)); PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str));
} else { } else {
PyErr_Format(type, "%s %s", SWIG_Python_str_AsChar(old_str), mesg); PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg);
} }
SWIG_Python_str_DelForPy3(tmp);
Py_DECREF(old_str); Py_DECREF(old_str);
} }
return 1; return 1;
@ -1540,6 +1545,7 @@ SWIG_Python_TypeError(const char *type, PyObject *obj)
if (cstr) { if (cstr) {
PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
type, otype, cstr); type, otype, cstr);
SWIG_Python_str_DelForPy3(cstr);
} else { } else {
PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received",
type, otype); type, otype);

View file

@ -6,19 +6,27 @@ SWIGINTERN int
SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
{ {
%#if PY_VERSION_HEX>=0x03000000 %#if PY_VERSION_HEX>=0x03000000
if (PyUnicode_Check(obj)) if (PyUnicode_Check(obj))
%#else %#else
if (PyString_Check(obj)) if (PyString_Check(obj))
%#endif %#endif
{ {
char *cstr; Py_ssize_t len; char *cstr; Py_ssize_t len;
%#if PY_VERSION_HEX>=0x03000000 %#if PY_VERSION_HEX>=0x03000000
if (!alloc && cptr) {
/* We can't allow converting without allocation, since the internal
representation of string in Python 3 is UCS-2/UCS-4 but we require
a UTF-8 representation.
TODO(bhy) More detailed explanation */
return SWIG_RuntimeError;
}
obj = PyUnicode_AsUTF8String(obj); obj = PyUnicode_AsUTF8String(obj);
PyBytes_AsStringAndSize(obj, &cstr, &len); PyBytes_AsStringAndSize(obj, &cstr, &len);
if(alloc) *alloc = SWIG_NEWOBJ;
%#else %#else
PyString_AsStringAndSize(obj, &cstr, &len); PyString_AsStringAndSize(obj, &cstr, &len);
%#endif %#endif
if (cptr) { if (cptr) {
if (alloc) { if (alloc) {
/* /*
In python the user should not be able to modify the inner In python the user should not be able to modify the inner
@ -43,10 +51,16 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
*alloc = SWIG_OLDOBJ; *alloc = SWIG_OLDOBJ;
} }
} else { } else {
%#if PY_VERSION_HEX>=0x03000000
assert(0); /* Should never reach here in Python 3 */
%#endif
*cptr = SWIG_Python_str_AsChar(obj); *cptr = SWIG_Python_str_AsChar(obj);
} }
} }
if (psize) *psize = len + 1; if (psize) *psize = len + 1;
%#if PY_VERSION_HEX>=0x03000000
Py_XDECREF(obj);
%#endif
return SWIG_OK; return SWIG_OK;
} else { } else {
swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();