Describe the bug
least_cost_corridor(..., precomputed=True) sums two cost-distance surfaces with corridor = cd_a + cd_b (in corridor.py, _compute_corridor) without first checking that the surfaces share a shape and grid. The normal (non-precomputed) path can't hit this, because cost_distance rejects mismatched inputs with raster.shape != friction.shape. The precomputed path skips cost_distance entirely, so nothing guards the addition.
When the two precomputed surfaces have different shapes, xarray aligns them on the intersection of their coordinates instead of raising. You get a silently truncated corridor with wrong values.
Reproduce
import numpy as np, xarray as xr
from xrspatial.corridor import least_cost_corridor
def mk(data):
h, w = data.shape
r = xr.DataArray(data.astype(float), dims=["y", "x"], attrs={"res": (1.0, 1.0)})
r["y"] = np.arange(h, dtype=float)
r["x"] = np.arange(w, dtype=float)
return r
cd_a = mk(np.ones((4, 4)))
cd_b = mk(np.ones((3, 3)))
out = least_cost_corridor(mk(np.ones((4, 4))), cd_a, cd_b, precomputed=True)
print(out.shape) # (3, 3) -- silently dropped a row and column
print(out.data) # all zeros
A related variant with same-size but non-overlapping coordinates produces an empty intersection and raises a confusing internal numpy.nanmin error instead of a clear validation message.
Expected behavior
Mismatched precomputed surfaces should raise a clear ValueError naming the offending parameter and the shapes, the way cost_distance already does for mismatched raster/friction. They should never silently produce a truncated, wrong-valued corridor.
Additional context
Found during a security sweep of corridor.py (dtype/shape confusion, silent wrong results). The fix is to validate matching shapes across the surfaces before computing, reusing _validate_matching_shape from xrspatial.utils.
Describe the bug
least_cost_corridor(..., precomputed=True)sums two cost-distance surfaces withcorridor = cd_a + cd_b(incorridor.py,_compute_corridor) without first checking that the surfaces share a shape and grid. The normal (non-precomputed) path can't hit this, becausecost_distancerejects mismatched inputs withraster.shape != friction.shape. The precomputed path skipscost_distanceentirely, so nothing guards the addition.When the two precomputed surfaces have different shapes, xarray aligns them on the intersection of their coordinates instead of raising. You get a silently truncated corridor with wrong values.
Reproduce
A related variant with same-size but non-overlapping coordinates produces an empty intersection and raises a confusing internal
numpy.nanminerror instead of a clear validation message.Expected behavior
Mismatched precomputed surfaces should raise a clear
ValueErrornaming the offending parameter and the shapes, the waycost_distancealready does for mismatched raster/friction. They should never silently produce a truncated, wrong-valued corridor.Additional context
Found during a security sweep of
corridor.py(dtype/shape confusion, silent wrong results). The fix is to validate matching shapes across the surfaces before computing, reusing_validate_matching_shapefromxrspatial.utils.