Skip to content

Commit

Permalink
corner cases tests and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
qchateau committed Oct 7, 2019
1 parent 36234db commit 06d1bb9
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 15 deletions.
25 changes: 11 additions & 14 deletions cbitstruct/_cbitstruct.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,10 +605,7 @@ static PyObject* parsed_elements_to_python(ParsedElement* elements, CompiledForm
};

if (!v) {
if (!PyErr_Occurred()) {
// Set our own exception
PyErr_SetString(PyExc_TypeError, "to-python conversion error");
}
// An exception has been set
Py_DECREF(result);
return NULL;
}
Expand Down Expand Up @@ -650,9 +647,9 @@ static Py_ssize_t PyArg_ParseTupleAndKeywordsFirstN(

if (PyArg_VaParseTupleAndKeywords(
actual_args, kwargs, format, keywords, varargs)) {
return_value = n_actual_args;
}
Py_DECREF(actual_args);
return_value = n_actual_args;

exit:
va_end(varargs);
Expand Down Expand Up @@ -1689,13 +1686,6 @@ byteswap_impl(PyObject *module, PyObject *fmt, Py_buffer *data,
goto exit;
}

return_value = PyBytes_FromStringAndSize(
((const char*)data->buf) + offset, data->len - offset);
if (!return_value) {
PyErr_NoMemory();
goto exit;
}

count_iter = PyMem_RawMalloc(length * sizeof(int));
if (!count_iter) {
PyErr_NoMemory();
Expand Down Expand Up @@ -1727,21 +1717,28 @@ byteswap_impl(PyObject *module, PyObject *fmt, Py_buffer *data,
}
}

if (sum > PyBytes_Size(return_value)) {
if (sum > data->len) {
PyErr_Format(
PyExc_TypeError,
"byteswap() requires a buffer of at least %d bytes",
sum);
goto exit;
}

uint8_t* buf = (uint8_t*)PyBytes_AS_STRING(return_value);
uint8_t* buf = (uint8_t*)data->buf + offset;
for (int i = 0; i < length; ++i) {
int nbytes = count_iter[i];
c_byteswitch(buf, nbytes);
buf += nbytes;
}

return_value = PyBytes_FromStringAndSize(
((const char*)data->buf) + offset, data->len - offset);
if (!return_value) {
PyErr_NoMemory();
goto exit;
}

exit:
if (count_iter) {
PyMem_RawFree(count_iter);
Expand Down
128 changes: 128 additions & 0 deletions cbitstruct/tests/test_cornercase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import unittest
import cbitstruct


NAMES = ["foo"]
FMT = "u32"
DICT = {"foo": 42}


class BitstructApiTest(unittest.TestCase):
def test_no_args(self):
self.assertRaises(Exception, cbitstruct.CompiledFormat)
self.assertRaises(Exception, cbitstruct.CompiledFormatDict)
self.assertRaises(Exception, cbitstruct.compile)

def test_not_unicode(self):
self.assertRaises(UnicodeDecodeError, cbitstruct.unpack, "t8", b"\xff")

def test_unpack_too_small(self):
self.assertRaises(TypeError, cbitstruct.unpack, FMT, b"")

def test_unpack_bad_args(self):
self.assertRaises(TypeError, cbitstruct.unpack)
self.assertRaises(TypeError, cbitstruct.unpack, None)
self.assertRaises(TypeError, cbitstruct.unpack, FMT)
self.assertRaises(TypeError, cbitstruct.unpack, FMT, None)
self.assertRaises(TypeError, cbitstruct.unpack, None, bytes(4))

def test_unpack_dict_too_small(self):
self.assertRaises(TypeError, cbitstruct.unpack_dict, FMT, NAMES, b"")

def test_unpack_dict_bad_args(self):
self.assertRaises(TypeError, cbitstruct.unpack_dict)
self.assertRaises(TypeError, cbitstruct.unpack_dict, None)
self.assertRaises(TypeError, cbitstruct.unpack_dict, FMT, None)
self.assertRaises(TypeError, cbitstruct.unpack_dict, FMT, NAMES, None)
self.assertRaises(TypeError, cbitstruct.unpack_dict, None, NAMES, bytes(4))
self.assertRaises(
TypeError, cbitstruct.unpack_dict, FMT, NAMES + ["extra"], bytes(4)
)

def test_unpack_from_too_small(self):
self.assertRaises(TypeError, cbitstruct.unpack_from, FMT, b"")

def test_unpack_from_bad_args(self):
self.assertRaises(TypeError, cbitstruct.unpack_from)
self.assertRaises(TypeError, cbitstruct.unpack_from, FMT)
self.assertRaises(TypeError, cbitstruct.unpack_from, None, bytes(4))
self.assertRaises(TypeError, cbitstruct.unpack_from, FMT, None)

def test_unpack_from_dict_too_small(self):
self.assertRaises(TypeError, cbitstruct.unpack_from_dict, FMT, NAMES, b"")

def test_unpack_from_dict_bad_args(self):
self.assertRaises(TypeError, cbitstruct.unpack_from_dict)
self.assertRaises(TypeError, cbitstruct.unpack_from_dict, FMT)
self.assertRaises(TypeError, cbitstruct.unpack_from_dict, FMT, None)
self.assertRaises(TypeError, cbitstruct.unpack_from_dict, None, NAMES)
self.assertRaises(TypeError, cbitstruct.unpack_from_dict, FMT, None, bytes(4))
self.assertRaises(TypeError, cbitstruct.unpack_from_dict, None, NAMES, bytes(4))
self.assertRaises(
TypeError, cbitstruct.unpack_from_dict, "g32", NAMES, bytes(4)
)
self.assertRaises(
TypeError, cbitstruct.unpack_from_dict, FMT, NAMES + ["extra"], bytes(4)
)
self.assertRaises(TypeError, cbitstruct.unpack_from_dict, FMT, NAMES, None)

def test_pack_bad_args(self):
self.assertRaises(TypeError, cbitstruct.pack)
self.assertRaises(TypeError, cbitstruct.pack, 0)

def test_pack_into_too_small(self):
self.assertRaises(TypeError, cbitstruct.pack_into, FMT, b"", 12)

def test_pack_into_bad_args(self):
self.assertRaises(TypeError, cbitstruct.pack_into)
self.assertRaises(TypeError, cbitstruct.pack_into, FMT)
self.assertRaises(TypeError, cbitstruct.pack_into, FMT, bytes(4))
self.assertRaises(TypeError, cbitstruct.pack_into, FMT, bytes(4), 0)
self.assertRaises(TypeError, cbitstruct.pack_into, None, bytes(4), 0, 12)
self.assertRaises(TypeError, cbitstruct.pack_into, "g32", bytes(4), 0, 12)

def test_pack_into_dict_too_small(self):
self.assertRaises(
TypeError, cbitstruct.pack_into_dict, FMT, NAMES, bytes(0), 0, DICT
)

def test_pack_into_dict_bad_args(self):
self.assertRaises(TypeError, cbitstruct.pack_into_dict)
self.assertRaises(TypeError, cbitstruct.pack_into_dict, FMT)
self.assertRaises(TypeError, cbitstruct.pack_into_dict, FMT, None)
self.assertRaises(TypeError, cbitstruct.pack_into_dict, None, NAMES)
self.assertRaises(TypeError, cbitstruct.pack_into_dict, FMT, NAMES, bytes(4), 0)
self.assertRaises(
TypeError, cbitstruct.pack_into_dict, FMT, None, bytes(4), 0, DICT
)
self.assertRaises(
TypeError, cbitstruct.pack_into_dict, None, NAMES, bytes(4), 0, DICT
)
self.assertRaises(
TypeError, cbitstruct.pack_into_dict, "g32", NAMES, bytes(4), 0, DICT
)

def test_pack_dict_bad_args(self):
self.assertRaises(TypeError, cbitstruct.pack_dict)
self.assertRaises(TypeError, cbitstruct.pack_dict, FMT)
self.assertRaises(TypeError, cbitstruct.pack_dict, FMT, None)
self.assertRaises(TypeError, cbitstruct.pack_dict, None, NAMES)
self.assertRaises(TypeError, cbitstruct.pack_dict, FMT, NAMES)
self.assertRaises(TypeError, cbitstruct.pack_dict, FMT, None, DICT)
self.assertRaises(TypeError, cbitstruct.pack_dict, None, NAMES, DICT)
self.assertRaises(TypeError, cbitstruct.pack_dict, "g32", NAMES, DICT)

def test_byteswap_bad_args(self):
self.assertRaises(TypeError, cbitstruct.byteswap, "23", b"")
self.assertRaises(TypeError, cbitstruct.byteswap, None, b"\xff")
self.assertRaises(TypeError, cbitstruct.byteswap, "23")
self.assertRaises(TypeError, cbitstruct.byteswap)

def test_calcsize_bad_args(self):
self.assertRaises(TypeError, cbitstruct.calcsize, "g32")
self.assertRaises(TypeError, cbitstruct.calcsize, None)
self.assertRaises(TypeError, cbitstruct.calcsize)


if __name__ == "__main__":
unittest.main()
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.1",
version="1.0.2",
author="Quentin CHATEAU",
author_email="[email protected]",
license="GPLv3",
Expand Down

0 comments on commit 06d1bb9

Please sign in to comment.