NULL pointer dereference in ImageItem_Grid::decode_grid_tile on missing tile reference
# NULL pointer dereference in decode_grid_tile when grid references non-existent tile
## Summary
`heif_image_handle_decode_image_tile()` crashes with a NULL pointer dereference in `ImageItem_Grid::decode_grid_tile()` when a grid image's `dimg` iref references a `heif_item_id` that does not exist in the file's item table. `HeifContext::get_image()` returns `nullptr`, and the function dereferences it without checking. The full-image decode path (`decode_full_grid_image`) correctly checks for null at line 317; the tile-by-tile path is the only one missing the guard.
This is the dominant crash class: 535 of 626 saved crashes (85%) from the heif-gaps fuzzer reduce to this single site.
## Reproduction
### Trigger condition
A HEIF file with a `grid` item whose `dimg` iref lists a tile_id that has no corresponding `infe` entry in the file.
### Trigger code
```c
heif_image* tile_img = NULL;
heif_error err = heif_image_handle_decode_image_tile(handle, &tile_img,
heif_colorspace_YCbCr,
heif_chroma_420,
NULL, /*x0=*/0, /*y0=*/0);
// SEGV inside libheif before err is set
```
### PoC file
`grid_null_repro.heif` (8256 bytes) -- smallest of 535 reproducers.
## ASAN stack trace
```
==2394260==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (READ)
#0 ImageItem_Grid::decode_grid_tile(...) libheif/image-items/grid.cc:590:31
#1 ImageItem_Grid::decode_compressed_image(...) libheif/image-items/grid.cc:224:12
#2 ImageItem::decode_image(...) libheif/image-items/image_item.cc:747:60
#3 HeifContext::decode_image(...) libheif/context.cc:1404:34
#4 heif_image_handle_decode_image_tile libheif/api/libheif/heif_tiling.cc:108:81
```
## Root cause
**File**: `libheif/image-items/grid.cc:589-590`
```cpp
std::shared_ptr<const ImageItem> tile_item = get_context()->get_image(tile_id, true); // nullptr when tile_id absent
if (auto error = tile_item->get_item_error()) { // NULL deref
return error;
}
```
`HeifContext::get_image()` returns `nullptr` when the requested `heif_item_id` is absent from `m_all_images`. The grid's `dimg` iref can reference any id -- no validation ensures each id corresponds to a real item.
The full-image path handles this correctly:
```cpp
// grid.cc:316-326 (decode_full_grid_image)
std::shared_ptr<const ImageItem> tileImg = get_context()->get_image(tileID, true);
if (!tileImg) { /* skip or error */ } // <-- correct handling
```
## Impact
- **Who**: Any application using per-tile decoding (`heif_image_handle_decode_image_tile`) on untrusted HEIF input. This is the documented path for memory-constrained decoders (mobile thumbnailers, viewers that lazily render large grids).
- **Severity**: DoS (crash). Not memory corruption -- `tile_item` is a true nullptr. No RCE potential.
- **OSS-Fuzz gap**: `file_fuzzer` uses full-image decode (`heif_decode_image` -> `decode_full_grid_image`), never the tile-by-tile API.
## Suggested Fix
Add a null check at `grid.cc:590`, matching the existing check at line 317:
```cpp
heif_item_id tile_id = m_grid_tile_ids[idx];
std::shared_ptr<const ImageItem> tile_item = get_context()->get_image(tile_id, true);
if (!tile_item) {
return Error{heif_error_Invalid_input,
heif_suberror_Missing_grid_images,
"Grid tile references a non-existent item"};
}
if (auto error = tile_item->get_item_error()) {
return error;
}
```
## Environment
- libheif: current HEAD as of 2026-05-07
- Compiler: clang with ASan + AFL++ instrumentation
- Harness: AFL++, 4 instances, ~18.6h runtime, 29-seed corpus
关闭于 2026-05-18 1 条评论