Index: Python/getargs.c =================================================================== --- Python/getargs.c (Revision 72701) +++ Python/getargs.c (Arbeitskopie) @@ -141,6 +141,7 @@ #define GETARGS_CAPSULE_NAME_CLEANUP_PTR "getargs.cleanup_ptr" #define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer" +#define GETARGS_CAPSULE_NAME_CLEANUP_CONVERT "getargs.cleanup_convert" static void cleanup_ptr(PyObject *self) @@ -194,7 +195,48 @@ return 0; } +static void +cleanup_convert(PyObject *self) +{ + typedef int (*destr_t)(PyObject *, void *); + destr_t destr = (destr_t)PyCapsule_GetContext(self); + void *ptr = PyCapsule_GetPointer(self, + GETARGS_CAPSULE_NAME_CLEANUP_CONVERT); + if (ptr && destr) + destr(NULL, ptr); +} + static int +addcleanup_convert(void *ptr, PyObject **freelist, int (*destr)(PyObject*,void*)) +{ + PyObject *cobj; + if (!*freelist) { + *freelist = PyList_New(0); + if (!*freelist) { + destr(NULL, ptr); + return -1; + } + } + cobj = PyCapsule_New(ptr, GETARGS_CAPSULE_NAME_CLEANUP_CONVERT, + cleanup_convert); + if (!cobj) { + destr(NULL, ptr); + return -1; + } + if (PyCapsule_SetContext(cobj, destr) == -1) { + /* This really should not happen. */ + Py_FatalError("capsule refused setting of context."); + return -1; + } + if (PyList_Append(*freelist, cobj)) { + Py_DECREF(cobj); + return -1; + } + Py_DECREF(cobj); + return 0; +} + +static int cleanreturn(int retval, PyObject *freelist) { if (freelist && retval != 0) { @@ -1253,10 +1295,15 @@ typedef int (*converter)(PyObject *, void *); converter convert = va_arg(*p_va, converter); void *addr = va_arg(*p_va, void *); + int res; format++; - if (! (*convert)(arg, addr)) + if (! (res = (*convert)(arg, addr))) return converterr("(unspecified)", arg, msgbuf, bufsize); + if (res == Py_CLEANUP_SUPPORTED && + addcleanup_convert(addr, freelist, convert) == -1) + return converterr("(cleanup problem)", + arg, msgbuf, bufsize); } else { p = va_arg(*p_va, PyObject **); Index: Include/modsupport.h =================================================================== --- Include/modsupport.h (Revision 72701) +++ Include/modsupport.h (Arbeitskopie) @@ -43,6 +43,8 @@ #define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c) #define PyModule_AddStringMacro(m, c) PyModule_AddStringConstant(m, #c, c) +#define Py_CLEANUP_SUPPORTED 0x20000 + #define PYTHON_API_VERSION 1013 #define PYTHON_API_STRING "1013" /* The API version is maintained (independently from the Python version) Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (Revision 72701) +++ Objects/unicodeobject.c (Arbeitskopie) @@ -1539,6 +1539,10 @@ PyObject *output = NULL; Py_ssize_t size; void *data; + if (arg == NULL) { + Py_DECREF(*(PyObject**)addr); + return 1; + } if (PyBytes_Check(arg) || PyByteArray_Check(arg)) { output = arg; Py_INCREF(output); @@ -1573,7 +1577,7 @@ return 0; } *(PyObject**)addr = output; - return 1; + return Py_CLEANUP_SUPPORTED; } Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (Revision 72701) +++ Modules/posixmodule.c (Arbeitskopie) @@ -787,8 +787,6 @@ if (!PyArg_ParseTuple(args, format, PyUnicode_FSConverter, &opath1, PyUnicode_FSConverter, &opath2)) { - Py_XDECREF(opath1); - Py_XDECREF(opath2); return NULL; } path1 = bytes2str(opath1, 1);