heic/heic
version 1.0
A single HEVC-coded still image in the real ISOBMFF/HEIF box layout (ftyp, meta/hdlr/pitm/iloc/iinf/infe, iprp/ipco/ispe/hvcC/pixi/colr, idat); the HEVC NAL payloads are container-correct shells, not a decodable bitstream
- Format
- High Efficiency Image File Format (heic)
- Authors
- The Fandango Fuzzer Team
- License
- Apache-2.0
- Fandango
- >=1.3
- Extensions
- heic
- Media type
- image/heic
- Specification
- https://www.iso.org/standard/89035.html
- Its files should decode
- never
- In the registry
- specs/heic/heic/heic.fan
Use it
fanbase install heic fandango fuzz -F heic -n 10
How it does
accepts 0%, covers 7.8%, 12/s. 1000 inputs, seed 1.
| Parser | Accepts | Version |
|---|---|---|
| ffmpeg | 0% | ffmpeg version 7.1.5-0+deb13u1 |
| imagemagick | 0% | Version: ImageMagick 7.1.1-43 Q16 x86_64 22550 |
| libheif-cov | 0% | libheif 1.23.6 |
| pillow | 0% | 12.3.0 |
The spec says its files decode never: as expected.
libheif-cov
- lines reached
- 7.8% of 22119
- real files reach
- 18.9%
- only the generated files
- 96 lines
- only the real files
- 2550 lines
Cite it
@software{fanbase_heic_heic_1_0,
author = {{The Fandango Fuzzer Team}},
title = {High Efficiency Image File Format (heic/heic), a Fandango input specification},
version = {1.0},
url = {https://github.com/fandango-fuzzer/fanbase},
note = {Fanbase registry, specs/heic/heic/heic.fan, sha256 479af94c4745},
}
Source
Source (229 lines)
# HEIC (ISO/IEC 23008-12): an ISOBMFF/HEIF box container -- ftyp, meta (hdlr,
# pitm, iloc, iinf/infe, iprp/ipco/ipma with ispe/hvcC/pixi/colr, idat)
# holding one HEVC-coded image item. Box sizes and the iloc/idat extent are
# tied to the generated bytes by `where` equalities.
#
# TODO:
# * The HEVC NAL payloads in idat and the VPS/SPS/PPS arrays are
# container-correct shells, not a decodable bitstream, so files rarely
# decode past the container level.
<start> ::= <heic_file>
<heic_file> ::= <ftyp_box> <meta_box>
# ftyp - File Type Box
<ftyp_box> ::= <ftyp_size> <ftyp_content>
<ftyp_size> ::= <u32>
<ftyp_content> ::= rb'ftyp' <major_brand> <minor_version> <compat_brands>
<major_brand> ::= rb'heic'
<minor_version>::= rb'\x00\x00\x00\x00'
<compat_brands>::= <brand>{2,5}
<brand> ::= rb'heic' | rb'heix' | rb'mif1' | rb'miaf' | rb'msf1' | rb'hevc'
# meta - Metadata Box (FullBox, version 0)
<meta_box> ::= <meta_size> <meta_content>
<meta_size> ::= <u32>
<meta_content> ::= rb'meta' <fullbox0> <hdlr_box> <pitm_box> <iloc_box> \
<iinf_box> <iprp_box> <idat_box>
# hdlr - Handler Reference Box (FullBox); handler_type must be 'pict'
<hdlr_box> ::= <hdlr_size> <hdlr_content>
<hdlr_size> ::= <u32>
<hdlr_content> ::= rb'hdlr' <fullbox0> <predefined> rb'pict' \
<hdlr_reserved> <handler_name>
<predefined> ::= rb'\x00\x00\x00\x00'
<hdlr_reserved>::= rb'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
<handler_name> ::= <name_chars> rb'\x00'
<name_chars> ::= <name_char>{0,16}
<name_char> ::= rb'[\x20-\x7e]'
# pitm - Primary Item Box (FullBox); item_ID = 1
<pitm_box> ::= <pitm_size> <pitm_content>
<pitm_size> ::= <u32>
<pitm_content> ::= rb'pitm' <fullbox0> <primary_item_id>
<primary_item_id> ::= rb'\x00\x01'
# iloc - Item Location Box (FullBox, version 1).
# offset_size=4, length_size=4, base_offset_size=0, index_size=0.
# One item (ID 1) with construction_method=1 (idat), one extent whose
# extent_offset=0 and extent_length == number of coded-image bytes in idat.
<iloc_box> ::= <iloc_size> <iloc_content>
<iloc_size> ::= <u32>
<iloc_content> ::= rb'iloc' <iloc_ver> <iloc_flags> <iloc_sizes> <iloc_base_index> \
<iloc_item_count> <iloc_item_id> <iloc_constr_method> \
<iloc_data_ref_index> <iloc_extent_count> \
<iloc_extent_offset> <iloc_extent_length>
<iloc_ver> ::= rb'\x01'
<iloc_flags> ::= rb'\x00\x00\x00'
<iloc_sizes> ::= rb'\x44'
<iloc_base_index> ::= rb'\x00'
<iloc_item_count> ::= rb'\x00\x01'
<iloc_item_id> ::= rb'\x00\x01'
<iloc_constr_method>::= rb'\x00\x01'
<iloc_data_ref_index>::= rb'\x00\x00'
<iloc_extent_count> ::= rb'\x00\x01'
<iloc_extent_offset>::= rb'\x00\x00\x00\x00'
<iloc_extent_length>::= <u32>
# iinf - Item Info Box (FullBox) with one infe entry
<iinf_box> ::= <iinf_size> <iinf_content>
<iinf_size> ::= <u32>
<iinf_content> ::= rb'iinf' <fullbox0> <iinf_entry_count> <infe_box>
<iinf_entry_count> ::= rb'\x00\x01'
# infe - Item Info Entry (FullBox, version 2); item_type = 'hvc1'
<infe_box> ::= <infe_size> <infe_content>
<infe_size> ::= <u32>
<infe_content> ::= rb'infe' <infe_ver> <infe_flags> <infe_item_id> \
<infe_prot_index> rb'hvc1' <infe_item_name>
<infe_ver> ::= rb'\x02'
<infe_flags> ::= rb'\x00\x00\x00'
<infe_item_id> ::= rb'\x00\x01'
<infe_prot_index>::= rb'\x00\x00'
<infe_item_name> ::= <name_chars> rb'\x00'
# iprp - Item Properties Box -> ipco (container) + ipma (association)
<iprp_box> ::= <iprp_size> <iprp_content>
<iprp_size> ::= <u32>
<iprp_content> ::= rb'iprp' <ipco_box> <ipma_box>
# ipco - Item Property Container Box (ordered list of property boxes)
<ipco_box> ::= <ipco_size> <ipco_content>
<ipco_size> ::= <u32>
<ipco_content> ::= rb'ipco' <ispe_box> <hvcC_box> <pixi_box> <colr_box>
# ispe - Image Spatial Extents (FullBox); width x height
<ispe_box> ::= <ispe_size> <ispe_content>
<ispe_size> ::= <u32>
<ispe_content> ::= rb'ispe' <fullbox0> <ispe_width> <ispe_height>
<ispe_width> ::= <dimension>
<ispe_height> ::= <dimension>
<dimension> ::= rb'\x00\x00\x00\x40' | rb'\x00\x00\x00\x80' \
| rb'\x00\x00\x01\x00' | rb'\x00\x00\x02\x00' \
| rb'\x00\x00\x04\x00' | rb'\x00\x00\x07\x80'
# hvcC - HEVC Configuration Box (HEVCDecoderConfigurationRecord).
# configurationVersion=1
# general_profile_space(2)+general_tier_flag(1)+general_profile_idc(5)
# general_profile_compatibility_flags (u32)
# general_constraint_indicator_flags (48 bits = 6 bytes)
# general_level_idc (u8)
# '1111' + min_spatial_segmentation_idc(12)
# '111111' + parallelismType(2)
# '111111' + chromaFormat(2)
# '11111' + bitDepthLumaMinus8(3)
# '11111' + bitDepthChromaMinus8(3)
# avgFrameRate (u16)
# constantFrameRate(2)+numTemporalLayers(3)+temporalIdNested(1)+lengthSizeMinusOne(2)
# numOfArrays (u8) = 3 (VPS, SPS, PPS)
<hvcC_box> ::= <hvcC_size> <hvcC_content>
<hvcC_size> ::= <u32>
<hvcC_content> ::= rb'hvcC' <hvcc_config_ver> <hvcc_profile> <hvcc_compat_flags> \
<hvcc_constraint_flags> <hvcc_level_idc> <hvcc_min_seg> \
<hvcc_parallelism> <hvcc_chroma_format> <hvcc_bitdepth_luma> \
<hvcc_bitdepth_chroma> <hvcc_avg_framerate> <hvcc_frame_info> \
<hvcc_num_arrays> <nal_array_vps> <nal_array_sps> <nal_array_pps>
<hvcc_config_ver> ::= rb'\x01'
<hvcc_profile> ::= rb'\x01' | rb'\x02' | rb'\x03' | rb'\x04'
<hvcc_compat_flags> ::= rb'\x60\x00\x00\x00' | rb'\x40\x00\x00\x00' | rb'\x20\x00\x00\x00'
<hvcc_constraint_flags>::= rb'\x00\x00\x00\x00\x00\x00' | rb'\x90\x00\x00\x00\x00\x00'
<hvcc_level_idc> ::= rb'\x5d' | rb'\x78' | rb'\x7b' | rb'\x99' | rb'\x9c'
<hvcc_min_seg> ::= rb'\xf0\x00'
<hvcc_parallelism> ::= rb'\xfc'
<hvcc_chroma_format> ::= rb'\xfd' | rb'\xfe' | rb'\xff'
<hvcc_bitdepth_luma> ::= rb'\xf8' | rb'\xf9' | rb'\xfa' | rb'\xfc'
<hvcc_bitdepth_chroma> ::= rb'\xf8' | rb'\xf9' | rb'\xfa' | rb'\xfc'
<hvcc_avg_framerate> ::= rb'\x00\x00'
<hvcc_frame_info> ::= rb'\x0f'
<hvcc_num_arrays> ::= rb'\x03'
# Each NAL array: header byte (array_completeness(1)+reserved(1)+NAL_unit_type(6)),
# numNalus:u16=1, then one NAL unit: nalUnitLength:u16 + nalUnit bytes.
# VPS=type 32 (0x20), SPS=type 33 (0x21), PPS=type 34 (0x22).
<nal_array_vps> ::= <nal_hdr_vps> <nal_count> <vps_len> <vps_data>
<nal_array_sps> ::= <nal_hdr_sps> <nal_count> <sps_len> <sps_data>
<nal_array_pps> ::= <nal_hdr_pps> <nal_count> <pps_len> <pps_data>
<nal_hdr_vps> ::= rb'\x20' | rb'\xa0'
<nal_hdr_sps> ::= rb'\x21' | rb'\xa1'
<nal_hdr_pps> ::= rb'\x22' | rb'\xa2'
<nal_count> ::= rb'\x00\x01'
<vps_len> ::= <u16>
<sps_len> ::= <u16>
<pps_len> ::= <u16>
<vps_data> ::= <byte>{6,40}
<sps_data> ::= <byte>{6,40}
<pps_data> ::= <byte>{4,32}
# pixi - Pixel Information (FullBox); 3 channels
<pixi_box> ::= <pixi_size> <pixi_content>
<pixi_size> ::= <u32>
<pixi_content> ::= rb'pixi' <fullbox0> <pixi_num_channels> <pixi_bits>
<pixi_num_channels> ::= rb'\x03'
<pixi_bits> ::= <pixi_depth> <pixi_depth> <pixi_depth>
<pixi_depth> ::= rb'\x08' | rb'\x0a' | rb'\x0c'
# colr - Colour Information Box, nclx profile
<colr_box> ::= <colr_size> <colr_content>
<colr_size> ::= <u32>
<colr_content> ::= rb'colr' rb'nclx' <colour_primaries> <transfer_char> \
<matrix_coeff> <full_range_byte>
<colour_primaries> ::= rb'\x00\x01' | rb'\x00\x02' | rb'\x00\x09' | rb'\x00\x0c'
<transfer_char> ::= rb'\x00\x01' | rb'\x00\x02' | rb'\x00\x0d' | rb'\x00\x10'
<matrix_coeff> ::= rb'\x00\x00' | rb'\x00\x01' | rb'\x00\x02' | rb'\x00\x09'
<full_range_byte> ::= rb'\x80' | rb'\x00'
# ipma - Item Property Association (FullBox); associates ipco entries with item 1
# entry_count:u32=1, item_ID:u16=1, association_count:u8=4,
# 4x association bytes: essential(1) | property_index(7) (1-based ipco order)
<ipma_box> ::= <ipma_size> <ipma_content>
<ipma_size> ::= <u32>
<ipma_content> ::= rb'ipma' <fullbox0> <ipma_entry_count> <ipma_item_id> \
<ipma_assoc_count> <ipma_assoc_ispe> <ipma_assoc_hvcc> \
<ipma_assoc_pixi> <ipma_assoc_colr>
<ipma_entry_count> ::= rb'\x00\x00\x00\x01'
<ipma_item_id> ::= rb'\x00\x01'
<ipma_assoc_count> ::= rb'\x04'
<ipma_assoc_ispe> ::= rb'\x01'
<ipma_assoc_hvcc> ::= rb'\x82'
<ipma_assoc_pixi> ::= rb'\x03'
<ipma_assoc_colr> ::= rb'\x04'
# idat - Item Data Box; the coded HEVC image bytes referenced by iloc.
# Shaped as a length-prefixed HEVC coded-slice NAL-unit shell.
<idat_box> ::= <idat_size> <idat_content>
<idat_size> ::= <u32>
<idat_content> ::= rb'idat' <hevc_image_data>
<hevc_image_data> ::= <hevc_nal_header> <hevc_nal_blob>
<hevc_nal_header> ::= rb'\x26\x01' | rb'\x28\x01' | rb'\x02\x01'
<hevc_nal_blob> ::= <byte>{16,512}
# Shared terminals
<fullbox0> ::= rb'\x00\x00\x00\x00'
<u32> ::= <byte> <byte> <byte> <byte>
<u16> ::= <byte> <byte>
<byte> ::= rb'[\x00-\xff]'
# Constraints: every box's size field == 4 (its own bytes) + the length of the
# rest of the box, tied to the actually-generated content; the iloc extent
# length == the number of coded-image bytes stored in idat; and each hvcC NAL
# array's nalUnitLength == the byte length of that NAL unit.
where bytes(<ftyp_size>) == (4 + len(bytes(<ftyp_content>))).to_bytes(4, 'big')
where bytes(<meta_size>) == (4 + len(bytes(<meta_content>))).to_bytes(4, 'big')
where bytes(<hdlr_size>) == (4 + len(bytes(<hdlr_content>))).to_bytes(4, 'big')
where bytes(<pitm_size>) == (4 + len(bytes(<pitm_content>))).to_bytes(4, 'big')
where bytes(<iloc_size>) == (4 + len(bytes(<iloc_content>))).to_bytes(4, 'big')
where bytes(<iinf_size>) == (4 + len(bytes(<iinf_content>))).to_bytes(4, 'big')
where bytes(<infe_size>) == (4 + len(bytes(<infe_content>))).to_bytes(4, 'big')
where bytes(<iprp_size>) == (4 + len(bytes(<iprp_content>))).to_bytes(4, 'big')
where bytes(<ipco_size>) == (4 + len(bytes(<ipco_content>))).to_bytes(4, 'big')
where bytes(<ispe_size>) == (4 + len(bytes(<ispe_content>))).to_bytes(4, 'big')
where bytes(<hvcC_size>) == (4 + len(bytes(<hvcC_content>))).to_bytes(4, 'big')
where bytes(<pixi_size>) == (4 + len(bytes(<pixi_content>))).to_bytes(4, 'big')
where bytes(<colr_size>) == (4 + len(bytes(<colr_content>))).to_bytes(4, 'big')
where bytes(<ipma_size>) == (4 + len(bytes(<ipma_content>))).to_bytes(4, 'big')
where bytes(<idat_size>) == (4 + len(bytes(<idat_content>))).to_bytes(4, 'big')
where bytes(<iloc_extent_length>) == len(bytes(<hevc_image_data>)).to_bytes(4, 'big')
where bytes(<vps_len>) == len(bytes(<vps_data>)).to_bytes(2, 'big')
where bytes(<sps_len>) == len(bytes(<sps_data>)).to_bytes(2, 'big')
where bytes(<pps_len>) == len(bytes(<pps_data>)).to_bytes(2, 'big')