Skip to content

least_cost_corridor(precomputed=True) silently truncates mismatched-shape surfaces #3445

Description

@brendancol

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:hydrologyArea: hydrologybugSomething isn't workingsweep-securityFound by /sweep-security

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions