Skip to content

Commit

Permalink
fix segmentation fault
Browse files Browse the repository at this point in the history
  • Loading branch information
qchateau committed Oct 6, 2019
1 parent 685f46e commit 36234db
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 15 deletions.
40 changes: 26 additions & 14 deletions cbitstruct/_cbitstruct.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,9 +633,15 @@ static Py_ssize_t PyArg_ParseTupleAndKeywordsFirstN(
va_list varargs;
va_start(varargs, n);

Py_ssize_t return_value = -1;
Py_ssize_t nkwargs = kwargs ? PyObject_Length(kwargs) : 0;
Py_ssize_t n_actual_args = n - nkwargs;

if (PyTuple_GET_SIZE(args) < n_actual_args) {
PyErr_SetString(PyExc_TypeError, "Not enough arguments");
goto exit;
}

PyObject* actual_args = PyTuple_GetSlice(args, 0, n_actual_args);
if (!actual_args) {
PyErr_NoMemory();
Expand All @@ -646,10 +652,11 @@ static Py_ssize_t PyArg_ParseTupleAndKeywordsFirstN(
actual_args, kwargs, format, keywords, varargs)) {
}
Py_DECREF(actual_args);
return_value = n_actual_args;

exit:
va_end(varargs);
return n_actual_args;
return return_value;
}

static bool PopFillPadding(PyObject* kwargs)
Expand Down Expand Up @@ -907,21 +914,22 @@ static PyObject* CompiledFormat_pack_into(
PyObject* kwargs)
{
PyObject* return_value = NULL;

bool fill_padding = PopFillPadding(kwargs);

Py_buffer buffer = {NULL, NULL};
Py_ssize_t offset = 0;

bool fill_padding = PopFillPadding(kwargs);
Py_ssize_t n_args = PyTuple_GET_SIZE(args);
PyObject** data = PySequence_Fast_ITEMS(args);

static char* _keywords[] = {"buf", "offset", NULL};
// custom (and vague) error message as all other 'pack_into'
// versions are processed by this function. Using the default
// error message would give bad information to the user
Py_ssize_t n_args_parsed = PyArg_ParseTupleAndKeywordsFirstN(
args, kwargs, "y*n:pack_into", _keywords, 2, &buffer, &offset);

Py_ssize_t n_args = PyTuple_GET_SIZE(args);
PyObject** data = PySequence_Fast_ITEMS(args);
if (n_args_parsed < 0) {
goto exit;
}

return_value = CompiledFormat_pack_into_raw(
self->compiled_fmt,
Expand All @@ -931,6 +939,7 @@ static PyObject* CompiledFormat_pack_into(
n_args - n_args_parsed,
fill_padding);

exit:
if (buffer.obj) {
PyBuffer_Release(&buffer);
}
Expand Down Expand Up @@ -1325,13 +1334,15 @@ static PyObject* pack(PyObject* module, PyObject* args, PyObject* kwargs)
{
PyObject* return_value = NULL;
const char* fmt = NULL;
PyCompiledFormatObject self;
memset(&self, 0, sizeof(self));

static char* _keywords[] = {"fmt", NULL};
Py_ssize_t n_args_parsed = PyArg_ParseTupleAndKeywordsFirstN(
args, kwargs, "s:pack", _keywords, 1, &fmt);

PyCompiledFormatObject self;
memset(&self, 0, sizeof(self));
if (n_args_parsed < 0) {
goto exit;
}

if (CompiledFormat___init___impl(&self, fmt)) {
// CompiledFormat___init___impl has set the exception
Expand Down Expand Up @@ -1363,15 +1374,16 @@ static PyObject* pack_into(PyObject* module, PyObject* args, PyObject* kwargs)
Py_buffer buffer = {NULL, NULL};
Py_ssize_t offset = 0;
const char* fmt = NULL;

PyCompiledFormatObject self;
memset(&self, 0, sizeof(self));
bool fill_padding = PopFillPadding(kwargs);

static char* _keywords[] = {"fmt", "buf", "offset", NULL};
Py_ssize_t n_args_parsed = PyArg_ParseTupleAndKeywordsFirstN(
args, kwargs, "sy*n:pack_into", _keywords, 3, &fmt, &buffer, &offset);

PyCompiledFormatObject self;
memset(&self, 0, sizeof(self));
if (n_args_parsed < 0) {
goto exit;
}

if (CompiledFormat___init___impl(&self, fmt)) {
// CompiledFormat___init___impl has set the exception
Expand Down
24 changes: 24 additions & 0 deletions cbitstruct/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@


class BitstructApiTest(unittest.TestCase):
def test_no_args(self):
self.assertRaises(Exception, cbitstruct.byteswap)
self.assertRaises(Exception, cbitstruct.calcsize)
self.assertRaises(Exception, cbitstruct.pack)
self.assertRaises(Exception, cbitstruct.pack_into)
self.assertRaises(Exception, cbitstruct.pack_dict)
self.assertRaises(Exception, cbitstruct.pack_into_dict)
self.assertRaises(Exception, cbitstruct.unpack)
self.assertRaises(Exception, cbitstruct.unpack_from)
self.assertRaises(Exception, cbitstruct.unpack_dict)
self.assertRaises(Exception, cbitstruct.unpack_from_dict)
self.assertRaises(Exception, cbitstruct.CompiledFormat)
self.assertRaises(Exception, cbitstruct.CompiledFormatDict)
cf = cbitstruct.CompiledFormat(FMT)
self.assertRaises(Exception, cf.pack)
self.assertRaises(Exception, cf.pack_into)
self.assertRaises(Exception, cf.unpack)
self.assertRaises(Exception, cf.unpack_from)
cfd = cbitstruct.CompiledFormatDict(FMT, NAMES)
self.assertRaises(Exception, cf.pack)
self.assertRaises(Exception, cf.pack_into)
self.assertRaises(Exception, cf.unpack)
self.assertRaises(Exception, cf.unpack_from)

def test_compiled_format(self):
cbitstruct.CompiledFormat(fmt=FMT)
cbitstruct.CompiledFormat(FMT)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

setup(
name="cbitstruct",
version="1.0.0",
version="1.0.1",
author="Quentin CHATEAU",
author_email="[email protected]",
license="GPLv3",
Expand Down

0 comments on commit 36234db

Please sign in to comment.