diff options
-rw-r--r-- | source3/python/py_tdbpack.c | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/source3/python/py_tdbpack.c b/source3/python/py_tdbpack.c index 446a2e5480..ba1e86384e 100644 --- a/source3/python/py_tdbpack.c +++ b/source3/python/py_tdbpack.c @@ -30,9 +30,7 @@ static int pytdbpack_calc_reqd_len(char *format_str, PyObject *val_seq); -static PyObject *pytdbpack_unpack_item(char, - char **pbuf, - int *plen); +static PyObject *pytdbpack_unpack_item(char, char **pbuf, int *plen, PyObject *); static PyObject *pytdbpack_pack_data(const char *format_str, PyObject *val_seq, @@ -220,8 +218,9 @@ pytdbpack_unpack(PyObject *self, format_len = strlen(format_str); - /* allocate list to hold results */ - val_list = PyList_New(format_len); + /* Allocate list to hold results. Initially empty, and we append + results as we go along. */ + val_list = PyList_New(0); if (!val_list) goto failed; ret_tuple = PyTuple_New(2); @@ -230,7 +229,6 @@ pytdbpack_unpack(PyObject *self, /* For every object, unpack. */ for (ppacked = packed_str, i = 0; i < format_len; i++) { - PyObject *val_obj; char format; format = format_str[i]; @@ -246,13 +244,9 @@ pytdbpack_unpack(PyObject *self, } } - val_obj = pytdbpack_unpack_item(format, - &ppacked, - &packed_len); - if (!val_obj) + if (!pytdbpack_unpack_item(format, &ppacked, &packed_len, val_list)) goto failed; - - PyList_SET_ITEM(val_list, i, val_obj); + last_format = format; } @@ -269,7 +263,8 @@ pytdbpack_unpack(PyObject *self, return ret_tuple; failed: - /* handle failure: deallocate anything */ + /* handle failure: deallocate anything. XDECREF forms handle NULL + pointers for objects that haven't been allocated yet. */ Py_XDECREF(val_list); Py_XDECREF(ret_tuple); Py_XDECREF(rest_string); @@ -482,12 +477,13 @@ unpack_string(char **pbuf, int *plen) static PyObject * -unpack_buffer(char **pbuf, int *plen) +unpack_buffer(char **pbuf, int *plen, PyObject *val_list) { /* first get 32-bit len */ long slen; unsigned char *b; unsigned char *start; + PyObject *str_obj = NULL, *len_obj = NULL; if (*plen < 4) { unpack_err_too_short(); @@ -518,7 +514,24 @@ unpack_buffer(char **pbuf, int *plen) (*pbuf) += slen; (*plen) -= slen; - return PyString_FromStringAndSize(start, slen); + if (!(len_obj = PyInt_FromLong(slen))) + goto failed; + + if (PyList_Append(val_list, len_obj) == -1) + goto failed; + + if (!(str_obj = PyString_FromStringAndSize(start, slen))) + goto failed; + + if (PyList_Append(val_list, str_obj) == -1) + goto failed; + + return val_list; + + failed: + Py_XDECREF(len_obj); /* handles NULL */ + Py_XDECREF(str_obj); + return NULL; } @@ -528,24 +541,27 @@ unpack_buffer(char **pbuf, int *plen) *PBUF is advanced, and *PLEN reduced to reflect the amount of data that has been consumed. - Returns a reference to the unpacked Python object, or NULL for failure. + Returns a reference to None, or NULL for failure. */ static PyObject *pytdbpack_unpack_item(char ch, char **pbuf, - int *plen) + int *plen, + PyObject *val_list) { + PyObject *result; + if (ch == 'w') { /* 16-bit int */ - return unpack_int16(pbuf, plen); + result = unpack_int16(pbuf, plen); } else if (ch == 'd' || ch == 'p') { /* 32-bit int */ /* pointers can just come through as integers */ - return unpack_uint32(pbuf, plen); + result = unpack_uint32(pbuf, plen); } else if (ch == 'f' || ch == 'P') { /* nul-term string */ - return unpack_string(pbuf, plen); + result = unpack_string(pbuf, plen); } else if (ch == 'B') { /* length, buffer */ - return unpack_buffer(pbuf, plen); + return unpack_buffer(pbuf, plen, val_list); } else { PyErr_Format(PyExc_ValueError, @@ -554,6 +570,14 @@ static PyObject *pytdbpack_unpack_item(char ch, return NULL; } + + /* otherwise OK */ + if (!result) + return NULL; + if (PyList_Append(val_list, result) == -1) + return NULL; + + return val_list; } |