Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mask index out of bounds segmentation fault #873

Merged
merged 1 commit into from Mar 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 24 additions & 11 deletions src_c/mask.c
Expand Up @@ -1443,26 +1443,39 @@ static PyObject *
mask_connected_component(PyObject *self, PyObject *args)
{
bitmask_t *input = pgMask_AsBitmap(self);
bitmask_t *output = bitmask_create(input->w, input->h);
pgMaskObject *maskobj = PyObject_New(pgMaskObject, &pgMask_Type);
int x, y;

x = -1;
bitmask_t *output = NULL;
pgMaskObject *maskobj = NULL;
int x = -1, y = -1;
Py_ssize_t args_exist = PyTuple_Size(args);

if (args_exist) {
if (!PyArg_ParseTuple(args, "|(ii)", &x, &y)) {
return NULL;
}

if (!PyArg_ParseTuple(args, "|(ii)", &x, &y)) {
return NULL;
if (x < 0 || x >= input->w || y < 0 || y >= input->h) {
return PyErr_Format(PyExc_IndexError, "%d, %d is out of bounds", x,
y);
}
}

/* if a coordinate is specified, make the pixel there is actually set */
if (x == -1 || bitmask_getbit(input, x, y)) {
output = bitmask_create(input->w, input->h);

/* If a pixel index is provided and the indexed bit is not set, then the
* returned mask is empty.
*/
if (!args_exist || bitmask_getbit(input, x, y)) {
if (largest_connected_comp(input, output, x, y) == -2) {
bitmask_free(output);
return RAISE(PyExc_MemoryError,
"Not enough memory to get bounding rects. \n");
"cannot allocate memory for connected component");
}
}

if (maskobj)
maskobj = PyObject_New(pgMaskObject, &pgMask_Type);
if (maskobj) {
maskobj->mask = output;
}

return (PyObject *)maskobj;
}
Expand Down
4 changes: 1 addition & 3 deletions test/mask_test.py
Expand Up @@ -892,13 +892,11 @@ def test_connected_component__unset_bit(self):
self.assertEqual(original_mask.get_size(), expected_size)
self.assertEqual(original_mask.get_at(unset_pos), 0)

# The skip() can be removed when issue #841 is fixed/closed.
@unittest.skip('can cause segmentation fault')
def test_connected_component__out_of_bounds(self):
"""Ensure connected_component() checks bounds."""
width, height = 19, 11
original_size = (width, height)
original_mask = pygame.mask.Mask(expected_size, fill=True)
original_mask = pygame.mask.Mask(original_size, fill=True)
original_count = original_mask.count()

for pos in ((0, -1), (-1, 0), (0, height + 1), (width + 1, 0)):
Expand Down