Skip to content

Commit

Permalink
filter: fix potentail FilterSource segfaults
Browse files Browse the repository at this point in the history
  • Loading branch information
pmrowla committed Nov 8, 2023
1 parent f0bfd89 commit 1f5c3b3
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 9 deletions.
4 changes: 2 additions & 2 deletions pygit2/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.

from typing import Callable, List
from typing import Callable, List, Optional

from ._pygit2 import FilterSource

Expand Down Expand Up @@ -58,7 +58,7 @@ class Filter:
def nattrs(cls) -> int:
return len(cls.attributes.split())

def check(self, src: FilterSource, attr_values: List[str]):
def check(self, src: FilterSource, attr_values: List[Optional[str]]):
"""
Check whether this filter should be applied to the given source.
Expand Down
40 changes: 33 additions & 7 deletions src/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,21 @@ PyDoc_STRVAR(FilterSource_repo__doc__,
PyObject *
FilterSource_repo__get__(FilterSource *self)
{
Repository *repo = PyObject_New(Repository, &RepositoryType);
git_repository *repo = git_filter_source_repo(self->src);
Repository *py_repo;

if (repo == NULL)
Py_RETURN_NONE;

py_repo = PyObject_New(Repository, &RepositoryType);
if (py_repo == NULL)
return NULL;
repo->repo = git_filter_source_repo(self->src);
repo->config = NULL;
repo->index = NULL;
repo->owned = 1;
return (PyObject *)repo;
py_repo->repo = repo;
py_repo->config = NULL;
py_repo->index = NULL;
py_repo->owned = 0;
Py_INCREF(py_repo);
return (PyObject *)py_repo;
}

PyDoc_STRVAR(FilterSource_path__doc__,
Expand Down Expand Up @@ -88,6 +95,15 @@ FilterSource_oid__get__(FilterSource *self)
return git_oid_to_python(oid);
}

PyDoc_STRVAR(FilterSource_mode__doc__,
"Filter mode (either GIT_FILTER_CLEAN or GIT_FILTER_SMUDGE).\n");

PyObject *
FilterSource_mode__get__(FilterSource *self)
{
return PyLong_FromUnsignedLong(git_filter_source_mode(self->src));
}

PyDoc_STRVAR(FilterSource_flags__doc__,
"GIT_FILTER_* flags to be applied to the data.\n");

Expand All @@ -102,6 +118,7 @@ PyGetSetDef FilterSource_getseters[] = {
GETTER(FilterSource, path),
GETTER(FilterSource, filemode),
GETTER(FilterSource, oid),
GETTER(FilterSource, mode),
GETTER(FilterSource, flags),
{NULL}
};
Expand Down Expand Up @@ -431,7 +448,16 @@ int pygit2_filter_check(
}
for (i = 0; i < nattrs; ++i)
{
if (PyList_Append(py_attrs, to_unicode_safe(attr_values[i], NULL)) < 0)
if (attr_values[i] == NULL)
{
if (PyList_SetItem(py_attrs, i, Py_None) < 0)
{
PyErr_Clear();
err = GIT_ERROR;
goto error;
}
}
else if (PyList_SetItem(py_attrs, i, to_unicode_safe(attr_values[i], NULL)) < 0)
{
PyErr_Clear();
err = GIT_ERROR;
Expand Down
2 changes: 2 additions & 0 deletions test/test_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def close(self, write_next):
class _PassthroughFilter(_Rot13Filter):

def check(self, src, attr_values):
assert attr_values == [None]
assert src.repo
raise Passthrough


Expand Down

0 comments on commit 1f5c3b3

Please sign in to comment.