ITADN

NULL pointer dereference in ImageItem_Grid::decode_grid_tile on missing tile reference

#1803Closedjortles 创建于 2026-05-18
J
jortlescommented
# 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 条评论