Describe the bug
circle_kernel() and annulus_kernel() in xrspatial/convolution.py take a radius (and outer_radius/inner_radius) with no upper bound. The kernel is built by _ellipse_kernel(half_w, half_h), where half_w = int(radius_meters / cellsize_x) and half_h = int(radius_meters / cellsize_y). The float64 array that comes out has shape (2*half_h + 1, 2*half_w + 1), so memory grows quadratically with the radius.
With no cap, one number from the caller can OOM the host:
circle_kernel(1, 1, 100000) gives half_w = half_h = 100000, so the float64 kernel is (200001, 200001) ~ 320 GB.
circle_kernel(1, 1, 1000000) is ~32 TB.
annulus_kernel calls circle_kernel twice, so the same hole applies to both its radii.
The kernel shape is also used as the convolution depth in convolve_2d, so the pad and dask map_overlap depth blow up with it.
Expected behavior
Reject a kernel whose required memory exceeds roughly half of available memory with a MemoryError that names the radius and the memory estimate.
Reproduction
from xrspatial.convolution import circle_kernel
circle_kernel(1, 1, 100000) # tries to allocate ~320 GB
Affected functions
circle_kernel (direct)
annulus_kernel (via two circle_kernel calls)
Both are public API. They are re-exported by xrspatial.focal and xrspatial.convolution and used across the docs and user-guide notebooks.
Severity
HIGH. One number passed to the public API can OOM the server.
Category
Cat 1 (unbounded allocation / DoS) per the security sweep.
Additional context
Found during the convolution security sweep on 2026-04-23. Same pattern as the bilateral fix (#1236) and the bump raster fix (#1231). One-fix-per-PR convention applies.
Describe the bug
circle_kernel()andannulus_kernel()inxrspatial/convolution.pytake aradius(andouter_radius/inner_radius) with no upper bound. The kernel is built by_ellipse_kernel(half_w, half_h), wherehalf_w = int(radius_meters / cellsize_x)andhalf_h = int(radius_meters / cellsize_y). The float64 array that comes out has shape(2*half_h + 1, 2*half_w + 1), so memory grows quadratically with the radius.With no cap, one number from the caller can OOM the host:
circle_kernel(1, 1, 100000)giveshalf_w = half_h = 100000, so the float64 kernel is(200001, 200001)~ 320 GB.circle_kernel(1, 1, 1000000)is ~32 TB.annulus_kernelcallscircle_kerneltwice, so the same hole applies to both its radii.The kernel shape is also used as the convolution depth in
convolve_2d, so the pad and daskmap_overlapdepth blow up with it.Expected behavior
Reject a kernel whose required memory exceeds roughly half of available memory with a
MemoryErrorthat names the radius and the memory estimate.Reproduction
Affected functions
circle_kernel(direct)annulus_kernel(via twocircle_kernelcalls)Both are public API. They are re-exported by
xrspatial.focalandxrspatial.convolutionand used across the docs and user-guide notebooks.Severity
HIGH. One number passed to the public API can OOM the server.
Category
Cat 1 (unbounded allocation / DoS) per the security sweep.
Additional context
Found during the convolution security sweep on 2026-04-23. Same pattern as the bilateral fix (#1236) and the bump raster fix (#1231). One-fix-per-PR convention applies.