Describe the bug
_assemble_tiles_kernel in xrspatial/geotiff/_gpu_decode.py reads tile_out_offsets[tile_idx] where tile_idx is computed from the output pixel's position (tile_row * tiles_across + tile_col). If a TIFF declares image dimensions implying more tiles than its TileOffsets tag supplies, tile_idx can exceed len(tile_out_offsets). The kernel then reads past the end of device memory.
The CPU path (_read_tiles) silently skips tiles whose index exceeds the offsets array, so the caller gets a zero-padded output instead of an error.
Reproduction
Craft a TIFF where:
ImageWidth / ImageLength and TileWidth / TileLength imply tiles_across * tiles_down = N tiles.
TileOffsets tag has count M with M < N.
On the GPU path (open_geotiff_gpu), the kernel launches one thread per output pixel. Threads whose pixel maps to a tile index >= M read past the end of d_decomp_offsets.
Expected behavior
The reader should reject the file with a ValueError during header parsing, naming the mismatch between the declared tile grid and the TileOffsets length.
Impact
- GPU path: out-of-bounds device read. Produces garbage pixels, or trips a CUDA illegal memory access that kills the process.
- CPU path: silent wrong output (zero-filled tiles where offsets were missing).
- Adversarial input only. Files written by
xrspatial.geotiff._writer or GDAL always have matching counts.
Context
Found during /sweep-security audit of the geotiff subpackage. Related to #1215 (tile dimension guard) and a separate predictor-kernel finding filed as a sibling issue.
Desktop:
- OS: Linux
- Python: 3.11
- xarray-spatial: current master
Describe the bug
_assemble_tiles_kernelinxrspatial/geotiff/_gpu_decode.pyreadstile_out_offsets[tile_idx]wheretile_idxis computed from the output pixel's position (tile_row * tiles_across + tile_col). If a TIFF declares image dimensions implying more tiles than its TileOffsets tag supplies,tile_idxcan exceedlen(tile_out_offsets). The kernel then reads past the end of device memory.The CPU path (
_read_tiles) silently skips tiles whose index exceeds the offsets array, so the caller gets a zero-padded output instead of an error.Reproduction
Craft a TIFF where:
ImageWidth/ImageLengthandTileWidth/TileLengthimplytiles_across * tiles_down = Ntiles.TileOffsetstag has countMwithM < N.On the GPU path (
open_geotiff_gpu), the kernel launches one thread per output pixel. Threads whose pixel maps to a tile index>= Mread past the end ofd_decomp_offsets.Expected behavior
The reader should reject the file with a
ValueErrorduring header parsing, naming the mismatch between the declared tile grid and the TileOffsets length.Impact
xrspatial.geotiff._writeror GDAL always have matching counts.Context
Found during
/sweep-securityaudit of the geotiff subpackage. Related to #1215 (tile dimension guard) and a separate predictor-kernel finding filed as a sibling issue.Desktop: