Skip to content

Commit 1f5c3b3

Browse files
committed
filter: fix potentail FilterSource segfaults
1 parent f0bfd89 commit 1f5c3b3

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

pygit2/filter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
2424
# Boston, MA 02110-1301, USA.
2525

26-
from typing import Callable, List
26+
from typing import Callable, List, Optional
2727

2828
from ._pygit2 import FilterSource
2929

@@ -58,7 +58,7 @@ class Filter:
5858
def nattrs(cls) -> int:
5959
return len(cls.attributes.split())
6060

61-
def check(self, src: FilterSource, attr_values: List[str]):
61+
def check(self, src: FilterSource, attr_values: List[Optional[str]]):
6262
"""
6363
Check whether this filter should be applied to the given source.
6464

src/filter.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,21 @@ PyDoc_STRVAR(FilterSource_repo__doc__,
4848
PyObject *
4949
FilterSource_repo__get__(FilterSource *self)
5050
{
51-
Repository *repo = PyObject_New(Repository, &RepositoryType);
51+
git_repository *repo = git_filter_source_repo(self->src);
52+
Repository *py_repo;
53+
5254
if (repo == NULL)
55+
Py_RETURN_NONE;
56+
57+
py_repo = PyObject_New(Repository, &RepositoryType);
58+
if (py_repo == NULL)
5359
return NULL;
54-
repo->repo = git_filter_source_repo(self->src);
55-
repo->config = NULL;
56-
repo->index = NULL;
57-
repo->owned = 1;
58-
return (PyObject *)repo;
60+
py_repo->repo = repo;
61+
py_repo->config = NULL;
62+
py_repo->index = NULL;
63+
py_repo->owned = 0;
64+
Py_INCREF(py_repo);
65+
return (PyObject *)py_repo;
5966
}
6067

6168
PyDoc_STRVAR(FilterSource_path__doc__,
@@ -88,6 +95,15 @@ FilterSource_oid__get__(FilterSource *self)
8895
return git_oid_to_python(oid);
8996
}
9097

98+
PyDoc_STRVAR(FilterSource_mode__doc__,
99+
"Filter mode (either GIT_FILTER_CLEAN or GIT_FILTER_SMUDGE).\n");
100+
101+
PyObject *
102+
FilterSource_mode__get__(FilterSource *self)
103+
{
104+
return PyLong_FromUnsignedLong(git_filter_source_mode(self->src));
105+
}
106+
91107
PyDoc_STRVAR(FilterSource_flags__doc__,
92108
"GIT_FILTER_* flags to be applied to the data.\n");
93109

@@ -102,6 +118,7 @@ PyGetSetDef FilterSource_getseters[] = {
102118
GETTER(FilterSource, path),
103119
GETTER(FilterSource, filemode),
104120
GETTER(FilterSource, oid),
121+
GETTER(FilterSource, mode),
105122
GETTER(FilterSource, flags),
106123
{NULL}
107124
};
@@ -431,7 +448,16 @@ int pygit2_filter_check(
431448
}
432449
for (i = 0; i < nattrs; ++i)
433450
{
434-
if (PyList_Append(py_attrs, to_unicode_safe(attr_values[i], NULL)) < 0)
451+
if (attr_values[i] == NULL)
452+
{
453+
if (PyList_SetItem(py_attrs, i, Py_None) < 0)
454+
{
455+
PyErr_Clear();
456+
err = GIT_ERROR;
457+
goto error;
458+
}
459+
}
460+
else if (PyList_SetItem(py_attrs, i, to_unicode_safe(attr_values[i], NULL)) < 0)
435461
{
436462
PyErr_Clear();
437463
err = GIT_ERROR;

test/test_filter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ def close(self, write_next):
3636
class _PassthroughFilter(_Rot13Filter):
3737

3838
def check(self, src, attr_values):
39+
assert attr_values == [None]
40+
assert src.repo
3941
raise Passthrough
4042

4143

0 commit comments

Comments
 (0)