Skip to content

Commit 85d4d81

Browse files
committed
[filters] Improve invalid geometry handling in GeometryFilter #187
Implemented safer handling of invalid geometry input by: - validating geometry in a custom SafeGeometryField - catching GEOSException, GDALException, ValueError and TypeError in GeometryFilter.filter This prevents server error like: "Invalid geometry pointer returned from OGR_G_CreateGeometryFromJson" and ensures a clean 400 ValidationError response instead. Fixes #187
1 parent c4729a1 commit 85d4d81

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

rest_framework_gis/filters.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
from django.contrib.gis.db import models
55
from django.contrib.gis.db.models.fields import BaseSpatialField
66
from django.contrib.gis.db.models.functions import GeometryDistance
7+
from django.contrib.gis.gdal.error import GDALException
78
from django.contrib.gis.geos import Point, Polygon
9+
from django.contrib.gis.geos.error import GEOSException
810
from django.core.exceptions import ImproperlyConfigured
911
from django.db.models import Q
10-
from rest_framework.exceptions import ParseError
12+
from rest_framework.exceptions import ParseError, ValidationError
1113
from rest_framework.filters import BaseFilterBackend
1214

1315
from .tilenames import tile_edges
@@ -91,15 +93,30 @@ def get_schema_operation_parameters(self, view):
9193
# backward compatibility
9294
InBBOXFilter = InBBoxFilter
9395

96+
class SafeGeometryField(forms.GeometryField):
97+
"""
98+
GeometryField that converts GEOS/GDAL errors into ValidationError.
99+
"""
100+
101+
def to_python(self, value):
102+
try:
103+
return super().to_python(value)
104+
except (GEOSException, GDALException, ValueError, TypeError):
105+
raise forms.ValidationError("Invalid geometry value.")
94106

95107
class GeometryFilter(django_filters.Filter):
96-
field_class = forms.GeometryField
108+
field_class = SafeGeometryField
97109

98110
def __init__(self, *args, **kwargs):
99111
kwargs.setdefault("widget", forms.TextInput)
100112
super().__init__(*args, **kwargs)
101-
102-
113+
114+
def filter(self, qs, value):
115+
try:
116+
return super().filter(qs, value)
117+
except (GEOSException, GDALException, ValueError, TypeError) as e:
118+
raise ValidationError(f"Invalid geometry value: {str(e)}")
119+
103120
class GeoFilterSet(django_filters.FilterSet):
104121
GEOFILTER_FOR_DBFIELD_DEFAULTS = {
105122
models.GeometryField: {"filterset_class": GeometryFilter},

0 commit comments

Comments
 (0)