Make the conv functions more robust.

Now we may leak the strings from _(c)fruni which should be looked up
case by case. The positive side is that we no longer point to (possibly)
invalid memory.

Strings used with touni funcs are suspected to leak as well.
This commit is contained in:
Kai Huuhko 2013-03-26 18:53:13 +00:00
parent 37b8ff89ae
commit 0f3c3999e3
3 changed files with 102 additions and 57 deletions

View File

@ -221,7 +221,8 @@
include "widget_header.pxi"
from libc.stdlib cimport free
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy
from object cimport Object
@ -756,31 +757,26 @@ cdef class Window(Object):
"""
def __set__(self, list profiles):
cdef unsigned int count = len(profiles)
elm_win_available_profiles_set(self.obj, convert_python_list_strings_to_array_of_strings(profiles), count)
self.available_profiles_set(profiles)
def __get__(self):
cdef:
char **profiles
unsigned int count
return self.available_profiles_get()
ret = elm_win_available_profiles_get(self.obj, &profiles, &count)
if ret is 0:
raise RuntimeError("No available profiles")
return convert_array_of_strings_to_python_list(profiles, count)
def available_profiles_set(self, list profiles):
cpdef available_profiles_set(self, list profiles):
cdef:
unsigned int count = len(profiles)
const_char **lst = convert_python_list_strings_to_array_of_strings(profiles)
const_char **array
unsigned int arr_len = len(profiles)
unsigned int i
elm_win_available_profiles_set(self.obj, lst, count)
for i in range(count):
free(<void *>lst[i])
free(lst)
try:
array = convert_python_list_strings_to_array_of_strings(profiles)
elm_win_available_profiles_set(self.obj, array, arr_len)
finally:
for i in range(arr_len):
free(<void *>array[i])
free(array)
def available_profiles_get(self):
cpdef available_profiles_get(self):
cdef:
char **profiles
unsigned int count

View File

@ -17,6 +17,7 @@
from cpython cimport PyObject, Py_INCREF, Py_DECREF#, PyMem_Malloc, PyMem_Free
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy, strdup
from efl cimport Eina_Bool, const_Eina_List, eina_list_append, const_void
from efl.c_eo cimport Eo as cEo
from efl.c_eo cimport eo_init, eo_shutdown, eo_del, eo_unref, eo_wref_add, eo_add, Eo_Class
@ -37,46 +38,85 @@ cdef int PY_REFCOUNT(object o):
cdef unicode _touni(char* s):
"""
Converts a char * to a python string object
Note: Remember to free the char * when it's no longer needed.
"""
return s.decode('UTF-8', 'strict') if s else None
cdef unicode _ctouni(const_char *s):
"""
Converts a const_char * to a python string object
Note: Remember to free the const_char * when it's no longer needed.
"""
return s.decode('UTF-8', 'strict') if s else None
cdef char *_fruni(s):
cdef char *c_string
cdef char *_fruni(object s):
"""
Converts a python string object to a char *
Note: Remember to free the char * when it's no longer needed.
"""
cdef:
char *c_string
str string
unicode unistr
if s is None:
return NULL
if isinstance(s, unicode):
string = s.encode('UTF-8')
# XXX: We lose reference here
c_string = string
unistr = s
string = unistr.encode('UTF-8')
return strdup(string)
elif isinstance(s, str):
c_string = s
# XXX: Reference is lost unless the user keeps the string object around
return strdup(s)
else:
raise TypeError("Expected str or unicode object, got %s" % (type(s).__name__))
return c_string
cdef const_char *_cfruni(s):
cdef const_char *c_string
cdef const_char *_cfruni(object s):
"""
Converts a python string object to a const_char *
Note: Remember to free the const_char * when it's no longer needed.
"""
cdef:
const_char *c_string
str string
unicode unistr
if s is None:
return NULL
if isinstance(s, unicode):
string = s.encode('UTF-8')
# XXX: We lose reference here
c_string = string
unistr = s
string = unistr.encode('UTF-8')
return strdup(string)
elif isinstance(s, str):
c_string = s
# XXX: Reference is lost unless the user keeps the string object around
return strdup(s)
else:
raise TypeError("Expected str or unicode object, got %s" % (type(s).__name__))
return c_string
cdef convert_array_of_strings_to_python_list(char **array, int array_length):
cdef list convert_array_of_strings_to_python_list(char **array, int array_length):
"""
Converts an array of strings to a python list.
Note: Remember to free the array when it's no longer needed.
"""
cdef char *string
ret = []
@ -89,24 +129,37 @@ cdef convert_array_of_strings_to_python_list(char **array, int array_length):
cdef const_char ** convert_python_list_strings_to_array_of_strings(list strings):
"""
Converts a python list to an array of strings.
Note: Remember to free the array when it's no longer needed.
"""
cdef:
const_char **lst
const_char **array
unsigned int arr_len = len(strings)
const_char *string
int count = len(strings)
unsigned int str_len
unsigned int i
lst = <const_char **>malloc(count * sizeof(const_char*))
for i in range(count):
array = <const_char **>malloc(arr_len * sizeof(const_char*))
if not array:
raise MemoryError()
for i in range(arr_len):
string = _cfruni(strings[i])
str_len = len(strings[i])
lst[i] = <const_char *>malloc(str_len + 1)
memcpy(lst[i], string, str_len + 1)
# Note: Always make sure that the array is freed at the other end.
return lst
str_len = len(string)
array[i] = <const_char *>malloc(str_len + 1)
memcpy(array[i], string, str_len + 1)
# Note: Always make sure that the array is freed at the other end
return array
cdef convert_eina_list_strings_to_python_list(const_Eina_List *lst):
cdef const_char *s
ret = []
cdef list convert_eina_list_strings_to_python_list(const_Eina_List *lst):
cdef:
const_char *s
list ret = []
while lst:
s = <const_char *>lst.data
if s != NULL:
@ -122,7 +175,7 @@ cdef Eina_List * convert_python_list_strings_to_eina_list(strings):
return lst
cdef _object_list_to_python(const_Eina_List *lst):
cdef list _object_list_to_python(const_Eina_List *lst):
ret = []
while lst:
ret.append(object_from_instance(<cEo *>lst.data))

View File

@ -20,10 +20,6 @@ from efl.c_eo cimport Eo_Class
from efl cimport Eina_List, const_Eina_List
from libc.string cimport const_char
cdef extern from "string.h":
void *memcpy(void *dst, void *src, int n)
char *strdup(char *str)
cdef class Eo(object):
cdef cEo *obj
cdef readonly data
@ -44,8 +40,8 @@ cdef char* _fruni(s)
cdef unicode _ctouni(const_char *s)
cdef const_char *_cfruni(s)
cdef convert_array_of_strings_to_python_list(char **array, int array_length)
cdef list convert_array_of_strings_to_python_list(char **array, int array_length)
cdef const_char ** convert_python_list_strings_to_array_of_strings(list strings)
cdef convert_eina_list_strings_to_python_list(const_Eina_List *lst)
cdef list convert_eina_list_strings_to_python_list(const_Eina_List *lst)
cdef Eina_List * convert_python_list_strings_to_eina_list(strings)
cdef _object_list_to_python(const_Eina_List *lst)
cdef list _object_list_to_python(const_Eina_List *lst)