Describe the bug
Reading an integer GeoTIFF whose GDAL_NODATA tag holds a non-finite string ("NaN", "nan", "inf") crashes the read with ValueError: cannot convert float NaN to integer. The crash fires at three sites in xrspatial/geotiff/__init__.py that call int(nodata) on the integer dtype branch without first checking whether the float is finite:
open_geotiff eager numpy path (line ~900)
_apply_nodata_mask_gpu GPU path (line ~971)
_delayed_read_window dask path (line ~2291)
The sibling helpers _resolve_masked_fill and _sparse_fill_value in xrspatial/geotiff/_reader.py already guard with not math.isnan(v) and not math.isinf(v) (issue #1581 / PR #1583), so the unguarded sites are an unfinished pass of the same fix.
Reproduction
A 2x2 uint16 TIFF whose GDAL_NODATA tag string is "nan":
import struct, tempfile, os
import numpy as np
from xrspatial.geotiff import open_geotiff
bo = '<'
pixels = np.array([[10, 20], [30, 40]], dtype=np.uint16)
def short_tag(tag, val):
return (tag, 3, 1, struct.pack(f'{bo}H', val))
def long_tag(tag, val):
return (tag, 4, 1, struct.pack(f'{bo}I', val))
def ascii_tag(tag, data):
return (tag, 2, len(data), data)
# ... assemble a minimal TIFF with GDAL_NODATA="nan\x00"
# (see test_nodata_nan_int_*.py for the full helper)
open_geotiff(path) # ValueError: cannot convert float NaN to integer
Expected behavior
The read should treat a non-finite nodata sentinel on an integer file as a no-op (no integer pixel can equal NaN, so the mask would be all-False) and leave the file dtype unchanged. This mirrors the out-of-range sentinel handling already in place for uint16 + GDAL_NODATA="-9999".
Categories
- Cat 2 (NaN propagation): a NaN nodata silently raises instead of being treated as missing
- Cat 5 (backend inconsistency):
_resolve_masked_fill and _sparse_fill_value already guard; the three __init__.py sites do not
Describe the bug
Reading an integer GeoTIFF whose
GDAL_NODATAtag holds a non-finite string ("NaN", "nan", "inf") crashes the read withValueError: cannot convert float NaN to integer. The crash fires at three sites inxrspatial/geotiff/__init__.pythat callint(nodata)on the integer dtype branch without first checking whether the float is finite:open_geotiffeager numpy path (line ~900)_apply_nodata_mask_gpuGPU path (line ~971)_delayed_read_windowdask path (line ~2291)The sibling helpers
_resolve_masked_filland_sparse_fill_valueinxrspatial/geotiff/_reader.pyalready guard withnot math.isnan(v) and not math.isinf(v)(issue #1581 / PR #1583), so the unguarded sites are an unfinished pass of the same fix.Reproduction
A 2x2 uint16 TIFF whose
GDAL_NODATAtag string is"nan":Expected behavior
The read should treat a non-finite nodata sentinel on an integer file as a no-op (no integer pixel can equal NaN, so the mask would be all-False) and leave the file dtype unchanged. This mirrors the out-of-range sentinel handling already in place for
uint16 + GDAL_NODATA="-9999".Categories
_resolve_masked_filland_sparse_fill_valuealready guard; the three__init__.pysites do not