Skip to content

from_template: cap eager coordinate allocation on the dask path#3585

Open
brendancol wants to merge 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-security-templates-2026-06-30-01
Open

from_template: cap eager coordinate allocation on the dask path#3585
brendancol wants to merge 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-security-templates-2026-06-30-01

Conversation

@brendancol

Copy link
Copy Markdown
Contributor

A fine resolution on a dask backend gets past both from_template size caps and then runs out of memory building the coordinate vectors at construction.

_MAX_CELLS is skipped on the dask backends because the grid data is lazy. _MAX_CHUNKS keys on block count, and the default tiling grows its block edge to keep that count near _DASK_MAX_BLOCKS, so a fine resolution never trips it. But _make_output_coords builds the x/y vectors eagerly with np.linspace, sized width + height, so:

from_template("conus", resolution=0.001, backend="dask")

would allocate ~72 GB of coordinates up front (a 3.1e9 x 5.9e9 grid, ~9e9 coordinate elements) while the grid data stays lazy and the chunk count sits around 2e5, under the 1M cap. Neither existing guard fires.

This PR adds _MAX_COORD_CELLS (1e9 elements, ~8 GB at float64) and checks width + height against it inside the dask branch. Eager backends are already bounded by _MAX_CELLS, so this only constrains the otherwise-unbounded dask path. The finest grid in the tests, conus at 1 m, is ~9e6 coordinate elements, well under the limit.

Test test_over_fine_dask_coord_alloc_raises covers the explicit-dask and chunks-promotion paths.

Found by the templates security sweep (resource-exhaustion / DoS).

A fine resolution on a dask backend gets past both size caps and then
runs out of memory building the coordinate vectors at construction.

The dask backends skip _MAX_CELLS because the grid data is lazy, and the
_MAX_CHUNKS guard keys on block count -- the default tiling grows its
block edge to keep that count near _DASK_MAX_BLOCKS, so a fine resolution
never trips it. But _make_output_coords builds the x/y vectors eagerly
with np.linspace, sized width + height, so
from_template("conus", resolution=0.001, backend="dask") would allocate
~72 GB of coordinates up front while the grid data stays lazy.

Add _MAX_COORD_CELLS (1e9 elements) and check width + height against it
in the dask branch. Eager backends are already bounded by _MAX_CELLS, so
this only constrains the otherwise-unbounded dask path; conus at 1 m,
the finest grid in the tests, is ~9e6 coordinate elements.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant