@@ -139,24 +139,35 @@ _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va)
139139
140140/* Handle cleanup of allocated memory in case of exception */
141141
142+ static void
143+ cleanup_ptr (void * ptr )
144+ {
145+ PyMem_FREE (ptr );
146+ }
147+
148+ static void
149+ cleanup_buffer (void * ptr )
150+ {
151+ PyBuffer_Release ((Py_buffer * ) ptr );
152+ }
153+
142154static int
143- addcleanup (void * ptr , PyObject * * freelist )
155+ addcleanup (void * ptr , PyObject * * freelist , void ( * destr )( void * ) )
144156{
145157 PyObject * cobj ;
146158 if (!* freelist ) {
147159 * freelist = PyList_New (0 );
148160 if (!* freelist ) {
149- PyMem_FREE (ptr );
161+ destr (ptr );
150162 return -1 ;
151163 }
152164 }
153- cobj = PyCObject_FromVoidPtr (ptr , NULL );
165+ cobj = PyCObject_FromVoidPtr (ptr , destr );
154166 if (!cobj ) {
155- PyMem_FREE (ptr );
167+ destr (ptr );
156168 return -1 ;
157169 }
158170 if (PyList_Append (* freelist , cobj )) {
159- PyMem_FREE (ptr );
160171 Py_DECREF (cobj );
161172 return -1 ;
162173 }
@@ -167,15 +178,15 @@ addcleanup(void *ptr, PyObject **freelist)
167178static int
168179cleanreturn (int retval , PyObject * freelist )
169180{
170- if (freelist ) {
171- if (retval == 0 ) {
172- Py_ssize_t len = PyList_GET_SIZE (freelist ), i ;
173- for (i = 0 ; i < len ; i ++ )
174- PyMem_FREE (PyCObject_AsVoidPtr (
175- PyList_GET_ITEM (freelist , i )));
176- }
177- Py_DECREF (freelist );
181+ if (freelist && retval != 0 ) {
182+ /* We were successful, reset the destructors so that they
183+ don't get called. */
184+ Py_ssize_t len = PyList_GET_SIZE (freelist ), i ;
185+ for (i = 0 ; i < len ; i ++ )
186+ ((PyCObject * ) PyList_GET_ITEM (freelist , i ))
187+ -> destructor = NULL ;
178188 }
189+ Py_XDECREF (freelist );
179190 return retval ;
180191}
181192
@@ -798,6 +809,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
798809 if (getbuffer (arg , p , & buf ) < 0 )
799810 return converterr (buf , arg , msgbuf , bufsize );
800811 }
812+ if (addcleanup (p , freelist , cleanup_buffer )) {
813+ return converterr (
814+ "(cleanup problem)" ,
815+ arg , msgbuf , bufsize );
816+ }
801817 format ++ ;
802818 } else if (* format == '#' ) {
803819 void * * p = (void * * )va_arg (* p_va , char * * );
@@ -875,6 +891,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
875891 if (getbuffer (arg , p , & buf ) < 0 )
876892 return converterr (buf , arg , msgbuf , bufsize );
877893 }
894+ if (addcleanup (p , freelist , cleanup_buffer )) {
895+ return converterr (
896+ "(cleanup problem)" ,
897+ arg , msgbuf , bufsize );
898+ }
878899 format ++ ;
879900 } else if (* format == '#' ) { /* any buffer-like object */
880901 void * * p = (void * * )va_arg (* p_va , char * * );
@@ -1051,7 +1072,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
10511072 "(memory error)" ,
10521073 arg , msgbuf , bufsize );
10531074 }
1054- if (addcleanup (* buffer , freelist )) {
1075+ if (addcleanup (* buffer , freelist , cleanup_ptr )) {
10551076 Py_DECREF (s );
10561077 return converterr (
10571078 "(cleanup problem)" ,
@@ -1096,7 +1117,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
10961117 return converterr ("(memory error)" ,
10971118 arg , msgbuf , bufsize );
10981119 }
1099- if (addcleanup (* buffer , freelist )) {
1120+ if (addcleanup (* buffer , freelist , cleanup_ptr )) {
11001121 Py_DECREF (s );
11011122 return converterr ("(cleanup problem)" ,
11021123 arg , msgbuf , bufsize );
@@ -1214,6 +1235,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
12141235 PyErr_Clear ();
12151236 return converterr ("read-write buffer" , arg , msgbuf , bufsize );
12161237 }
1238+ if (addcleanup (p , freelist , cleanup_buffer )) {
1239+ return converterr (
1240+ "(cleanup problem)" ,
1241+ arg , msgbuf , bufsize );
1242+ }
12171243 if (!PyBuffer_IsContiguous ((Py_buffer * )p , 'C' ))
12181244 return converterr ("contiguous buffer" , arg , msgbuf , bufsize );
12191245 break ;
0 commit comments