Opened 107 minutes ago
Last modified 104 minutes ago
#37491 assigned Bug
GeometryField crashes with RecursionError on deeply nested GeoJSON
| Reported by: | Philip Sørensen | Owned by: | |
|---|---|---|---|
| Component: | GIS | Version: | dev |
| Severity: | Release blocker | Keywords: | |
| Cc: | Philip Sørensen | Triage Stage: | Unreviewed |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
The ExternalCRSBlocker.check() added for CVE-2026-111362 (ecb2b77b49) parses GeoJSON input with json.loads() and doesn't catch RecursionError. When the input is nested more deeply than the recursion limit, e.g. a Point with 100,000 nested [ in coordinates, forms.GeometryField.clean() raises RecursionError (HTTP 500) instead of a ValidationError. This also applies to the default widget and the admin. BaseGeometryWidget.deserialize() only catches GEOSException, GDALException, ValueError and TypeError.
On 6.1.2 the same input gives "Invalid geometry value.", so this is a regression in 6.1.3, and presumably 6.0.10 and 5.2.19 too, since the fix was backported.
`python
from django.contrib.gis import forms
n = 100_000
forms.GeometryField().clean('{"type": "Point", "coordinates": ' + "* n +" * n + "}")
# 6.1.2: ValidationError; 6.1.3 / main: RecursionError
`
Patch: in ExternalCRSBlocker.check(), re-raise RecursionError from json.loads() as a ValueError, so that it's handled like the JSONDecodeError (a ValueError subclass) that callers already handle. Like #37418, the test mocks json.loads(), because the depth at which it raises depends on the interpreter's stack size.