static int vgetargs1(PyObject *, char *, va_list *, int);
static void seterror(int, char *, int *, char *, char *);
static char *convertitem(PyObject *, char **, va_list *, int *, char *,
- size_t);
+ size_t, PyObject **);
static char *converttuple(PyObject *, char **, va_list *,
- int *, char *, size_t, int);
-static char *convertsimple(PyObject *, char **, va_list *, char *, size_t);
+ int *, char *, size_t, int, PyObject **);
+static char *convertsimple(PyObject *, char **, va_list *, char *,
+ size_t, PyObject **);
static int convertbuffer(PyObject *, void **p, char **);
static int vgetargskeywords(PyObject *, PyObject *,
}
+/* Handle cleanup of allocated memory in case of exception */
+
+static int
+addcleanup(void *ptr, PyObject **freelist)
+{
+ PyObject *cobj;
+ if (!*freelist) {
+ *freelist = PyList_New(0);
+ if (!*freelist) {
+ PyMem_FREE(ptr);
+ return -1;
+ }
+ }
+ cobj = PyCObject_FromVoidPtr(ptr, NULL);
+ if (!cobj) {
+ PyMem_FREE(ptr);
+ return -1;
+ }
+ if(PyList_Append(*freelist, cobj)) {
+ PyMem_FREE(ptr);
+ Py_DECREF(cobj);
+ return -1;
+ }
+ Py_DECREF(cobj);
+ return 0;
+}
+
+static int
+cleanreturn(int retval, PyObject *freelist)
+{
+ if(freelist) {
+ if((retval) == 0) {
+ int len = PyList_GET_SIZE(freelist), i;
+ for (i = 0; i < len; i++)
+ PyMem_FREE(PyCObject_AsVoidPtr(
+ PyList_GET_ITEM(freelist, i)));
+ }
+ Py_DECREF(freelist);
+ }
+ return retval;
+}
+
+
static int
vgetargs1(PyObject *args, char *format, va_list *p_va, int compat)
{
char *formatsave = format;
int i, len;
char *msg;
+ PyObject *freelist = NULL;
assert(compat || (args != (PyObject*)NULL));
return 0;
}
msg = convertitem(args, &format, p_va, levels, msgbuf,
- sizeof(msgbuf));
+ sizeof(msgbuf), &freelist);
if (msg == NULL)
- return 1;
+ return cleanreturn(1, freelist);
seterror(levels[0], msg, levels+1, fname, message);
- return 0;
+ return cleanreturn(0, freelist);
}
else {
PyErr_SetString(PyExc_SystemError,
if (*format == '|')
format++;
msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
- levels, msgbuf, sizeof(msgbuf));
+ levels, msgbuf, sizeof(msgbuf), &freelist);
if (msg) {
seterror(i+1, msg, levels, fname, message);
- return 0;
+ return cleanreturn(0, freelist);
}
}
*format != '|' && *format != ':' && *format != ';') {
PyErr_Format(PyExc_SystemError,
"bad format string: %.200s", formatsave);
- return 0;
+ return cleanreturn(0, freelist);
}
- return 1;
+ return cleanreturn(1, freelist);
}
static char *
converttuple(PyObject *arg, char **p_format, va_list *p_va, int *levels,
- char *msgbuf, size_t bufsize, int toplevel)
+ char *msgbuf, size_t bufsize, int toplevel, PyObject **freelist)
{
int level = 0;
int n = 0;
PyObject *item;
item = PySequence_GetItem(arg, i);
msg = convertitem(item, &format, p_va, levels+1, msgbuf,
- bufsize);
+ bufsize, freelist);
/* PySequence_GetItem calls tp->sq_item, which INCREFs */
Py_XDECREF(item);
if (msg != NULL) {
static char *
convertitem(PyObject *arg, char **p_format, va_list *p_va, int *levels,
- char *msgbuf, size_t bufsize)
+ char *msgbuf, size_t bufsize, PyObject **freelist)
{
char *msg;
char *format = *p_format;
if (*format == '(' /* ')' */) {
format++;
msg = converttuple(arg, &format, p_va, levels, msgbuf,
- bufsize, 0);
+ bufsize, 0, freelist);
if (msg == NULL)
format++;
}
else {
- msg = convertsimple(arg, &format, p_va, msgbuf, bufsize);
+ msg = convertsimple(arg, &format, p_va, msgbuf, bufsize,
+ freelist);
if (msg != NULL)
levels[0] = 0;
}
static char *
convertsimple(PyObject *arg, char **p_format, va_list *p_va, char *msgbuf,
- size_t bufsize)
+ size_t bufsize, PyObject **freelist)
{
char *format = *p_format;
char c = *format++;
int *buffer_len = va_arg(*p_va, int *);
format++;
- if (buffer_len == NULL)
+ if (buffer_len == NULL) {
+ Py_DECREF(s);
return converterr(
"(buffer_len is NULL)",
arg, msgbuf, bufsize);
+ }
if (*buffer == NULL) {
*buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) {
"(memory error)",
arg, msgbuf, bufsize);
}
+ if(addcleanup(*buffer, freelist)) {
+ Py_DECREF(s);
+ return converterr(
+ "(cleanup problem)",
+ arg, msgbuf, bufsize);
+ }
} else {
if (size + 1 > *buffer_len) {
Py_DECREF(s);
PyMem_Free()ing it after usage
*/
- if ((int)strlen(PyString_AS_STRING(s)) != size)
+ if ((int)strlen(PyString_AS_STRING(s)) != size) {
+ Py_DECREF(s);
return converterr(
"(encoded string without NULL bytes)",
arg, msgbuf, bufsize);
+ }
*buffer = PyMem_NEW(char, size + 1);
if (*buffer == NULL) {
Py_DECREF(s);
return converterr("(memory error)",
arg, msgbuf, bufsize);
}
+ if(addcleanup(*buffer, freelist)) {
+ Py_DECREF(s);
+ return converterr("(cleanup problem)",
+ arg, msgbuf, bufsize);
+ }
memcpy(*buffer,
PyString_AS_STRING(s),
size + 1);
char *formatsave;
int i, len, nargs, nkeywords;
char *msg, **p;
+ PyObject *freelist = NULL;
assert(args != NULL && PyTuple_Check(args));
assert(keywords == NULL || PyDict_Check(keywords));
if (*format == '|')
format++;
msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
- levels, msgbuf, sizeof(msgbuf));
+ levels, msgbuf, sizeof(msgbuf), &freelist);
if (msg) {
seterror(i+1, msg, levels, fname, message);
- return 0;
+ return cleanreturn(0, freelist);
}
}
/* handle no keyword parameters in call */
if (nkeywords == 0)
- return 1;
+ return cleanreturn(1, freelist);
/* convert the keyword arguments; this uses the format
string where it was left after processing args */
if (item != NULL) {
Py_INCREF(item);
msg = convertitem(item, &format, p_va, levels, msgbuf,
- sizeof(msgbuf));
+ sizeof(msgbuf), &freelist);
Py_DECREF(item);
if (msg) {
seterror(i+1, msg, levels, fname, message);
- return 0;
+ return cleanreturn(0, freelist);
}
--nkeywords;
if (nkeywords == 0)
break;
}
else if (PyErr_Occurred())
- return 0;
+ return cleanreturn(0, freelist);
else {
msg = skipitem(&format, p_va);
if (msg) {
seterror(i+1, msg, levels, fname, message);
- return 0;
+ return cleanreturn(0, freelist);
}
}
}
if (!PyString_Check(key)) {
PyErr_SetString(PyExc_TypeError,
"keywords must be strings");
- return 0;
+ return cleanreturn(0, freelist);
}
ks = PyString_AsString(key);
for (i = 0; i < max; i++) {
"'%s' is an invalid keyword "
"argument for this function",
ks);
- return 0;
+ return cleanreturn(0, freelist);
}
}
}
- return 1;
+ return cleanreturn(1, freelist);
}