Fanbase

tiff/tiff

version 1.0

TIFF in eight fixed layouts: both byte orders, tiled, palette, multi-page, SubIFD, BigTIFF

Format
Tagged Image File Format (tiff)
Authors
The Fandango Fuzzer Team
License
Apache-2.0
Fandango
>=1.3
Extensions
tif, tiff
Media type
image/tiff
Specification
https://download.osgeo.org/libtiff/doc/TIFF6.pdf
Its files should decode
always
In the registry
specs/tiff/tiff/tiff.fan

Use it

fanbase install tiff
fandango fuzz -F tiff -n 10

How it does

accepts 100%, covers 10.8%, 63/s. 1000 inputs, seed 1.

ParserAcceptsVersion
ffmpeg88%ffmpeg version 7.1.5-0+deb13u1
imagemagick100%Version: ImageMagick 7.1.1-43 Q16 x86_64 22550
libtiff-cov100%libtiff 4.7.2
pillow85%12.3.0
tiffinfo100%

The spec says its files decode always: as expected.

libtiff-cov

lines reached
10.8% of 14513
real files reach
18.2%
only the generated files
183 lines
only the real files
1254 lines
8.9% after 1 inputs, 10.8% after 1000real files: 18.2%

Cite it

@software{fanbase_tiff_tiff_1_0,
  author  = {{The Fandango Fuzzer Team}},
  title   = {Tagged Image File Format (tiff/tiff), a Fandango input specification},
  version = {1.0},
  url     = {https://github.com/fandango-fuzzer/fanbase},
  note    = {Fanbase registry, specs/tiff/tiff/tiff.fan, sha256 f6892c10a739},
}

Source

Source (103 lines)
# TIFF with exact offsets in a handful of fixed layouts: little and big endian
# RGB, tiled gray, palette, two pages, nested SubIFD, a legacy variant, and
# BigTIFF.
#
# TODO:
# * Mostly derived from existing TIFF files, so not as much of a specification as it could be.
# * Replace constant strings with computed values.

<start> ::= <classic_le_rgb> | <classic_be_rgb> | <classic_le_tiled> | <classic_le_palette> | <classic_le_multipage> | <classic_le_nested> | <classic_le_legacy> | <bigtiff_le>
where len(str(<start>)) >= 150
where len(str(<start>)) <= 1662

# Classic RGB, chunky, uncompressed, one strip, rational values out of line.
<classic_le_rgb> ::= "II\x2a\x00\x08\x00\x00\x00" <le_rgb_ifd> <padding_86> <le_bits_rgb> <le_resolution> <le_resolution> <software_value> <rgb_pixels>
<le_rgb_ifd> ::= "\x0d\x00" <le_entry_width_2> <le_entry_height_2> "\x02\x01\x03\x00\x03\x00\x00\x00\x00\x01\x00\x00" <le_entry_compression_none> <le_entry_photo_rgb> "\x11\x01\x04\x00\x01\x00\x00\x00\x1e\x01\x00\x00" <le_entry_spp_3> <le_entry_rows_2> "\x17\x01\x04\x00\x01\x00\x00\x00\x0c\x00\x00\x00" "\x1a\x01\x05\x00\x01\x00\x00\x00\x06\x01\x00\x00" "\x1b\x01\x05\x00\x01\x00\x00\x00\x0e\x01\x00\x00" <le_entry_resolution_unit> "\x31\x01\x02\x00\x08\x00\x00\x00\x16\x01\x00\x00" "\x00\x00\x00\x00"
<le_bits_rgb> ::= "\x08\x00\x08\x00\x08\x00"
<le_resolution> ::= "\x48\x00\x00\x00\x01\x00\x00\x00" | "\x2c\x01\x00\x00\x01\x00\x00\x00" | "\x01\x00\x00\x00\x01\x00\x00\x00"
<software_value> ::= <software_text> "\x00"
<software_text> ::= "FAN-TIF" | "TIFF6.0" | "Example"
<rgb_pixels> ::= <octet>{12,12}

# Same baseline layout in Motorola byte order.
<classic_be_rgb> ::= "MM\x00\x2a\x00\x00\x00\x08" <be_rgb_ifd> <padding_86> <be_bits_rgb> <be_resolution> <be_resolution> <software_value> <rgb_pixels>
<be_rgb_ifd> ::= "\x00\x0d" "\x01\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x02" "\x01\x01\x00\x04\x00\x00\x00\x01\x00\x00\x00\x02" "\x01\x02\x00\x03\x00\x00\x00\x03\x00\x00\x01\x00" "\x01\x03\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00" "\x01\x06\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00" "\x01\x11\x00\x04\x00\x00\x00\x01\x00\x00\x01\x1e" "\x01\x15\x00\x03\x00\x00\x00\x01\x00\x03\x00\x00" "\x01\x16\x00\x04\x00\x00\x00\x01\x00\x00\x00\x02" "\x01\x17\x00\x04\x00\x00\x00\x01\x00\x00\x00\x0c" "\x01\x1a\x00\x05\x00\x00\x00\x01\x00\x00\x01\x06" "\x01\x1b\x00\x05\x00\x00\x00\x01\x00\x00\x01\x0e" "\x01\x28\x00\x03\x00\x00\x00\x01\x00\x02\x00\x00" "\x01\x31\x00\x02\x00\x00\x00\x08\x00\x00\x01\x16" "\x00\x00\x00\x00"
<be_bits_rgb> ::= "\x00\x08\x00\x08\x00\x08"
<be_resolution> ::= "\x00\x00\x00\x48\x00\x00\x00\x01" | "\x00\x00\x01\x2c\x00\x00\x00\x01" | "\x00\x00\x00\x01\x00\x00\x00\x01"

# Tiled grayscale: one 4x4 tile and the tile-specific tag quartet.
<classic_le_tiled> ::= "II\x2a\x00\x08\x00\x00\x00" <le_tiled_ifd> <padding_122> <gray_tile>
<le_tiled_ifd> ::= "\x0a\x00" <le_entry_width_4> <le_entry_height_4> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_gray> <le_entry_spp_1> "\x42\x01\x04\x00\x01\x00\x00\x00\x04\x00\x00\x00" "\x43\x01\x04\x00\x01\x00\x00\x00\x04\x00\x00\x00" "\x44\x01\x04\x00\x01\x00\x00\x00\x00\x01\x00\x00" "\x45\x01\x04\x00\x01\x00\x00\x00\x10\x00\x00\x00" "\x00\x00\x00\x00"
<gray_tile> ::= <octet>{16,16}

# Palette color: full 256-entry, three-plane ColorMap followed by four indices.
<classic_le_palette> ::= "II\x2a\x00\x08\x00\x00\x00" <le_palette_ifd> <color_map> <palette_pixels>
<le_palette_ifd> ::= "\x09\x00" <le_entry_width_2> <le_entry_height_2> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_palette> "\x11\x01\x04\x00\x01\x00\x00\x00\x7a\x06\x00\x00" <le_entry_rows_2> "\x17\x01\x04\x00\x01\x00\x00\x00\x04\x00\x00\x00" "\x40\x01\x03\x00\x00\x03\x00\x00\x7a\x00\x00\x00" "\x00\x00\x00\x00"
<color_map> ::= <le_zero_short>{256,256} <le_ff_short>{256,256} <le_ramp_short>{256,256}
<le_zero_short> ::= "\x00\x00"
<le_ff_short> ::= "\x7f\x7f"
<le_ramp_short> ::= "\x00\x00" | "\x00\x20" | "\x00\x40" | "\x00\x60" | "\x7f\x7f"
<palette_pixels> ::= <octet>{4,4}

# Two top-level pages connected through the classic next-IFD pointer.
<classic_le_multipage> ::= "II\x2a\x00\x08\x00\x00\x00" <le_page1_ifd> <le_page2_ifd> <padding_20> <gray_sample> <gray_sample>
<le_page1_ifd> ::= "\x09\x00" <le_entry_width_1> <le_entry_height_1> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_gray> "\x11\x01\x04\x00\x01\x00\x00\x00\x00\x01\x00\x00" <le_entry_spp_1> <le_entry_rows_1> <le_entry_bytecount_1> "\x7a\x00\x00\x00"
<le_page2_ifd> ::= "\x09\x00" <le_entry_width_1> <le_entry_height_1> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_gray> "\x11\x01\x04\x00\x01\x00\x00\x00\x01\x01\x00\x00" <le_entry_spp_1> <le_entry_rows_1> <le_entry_bytecount_1> "\x00\x00\x00\x00"
<gray_sample> ::= <octet>

# Three bounded SubIFD levels; padding selects byte-safe exact target offsets.
<classic_le_nested> ::= "II\x2a\x00\x08\x00\x00\x00" <le_nested_main_ifd> <padding_122> <le_nested_sub_ifd> <padding_130> <le_nested_deep_ifd> <padding_142> <gray_sample> <gray_sample> <gray_sample>
<le_nested_main_ifd> ::= "\x0a\x00" <le_entry_width_1> <le_entry_height_1> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_gray> "\x11\x01\x04\x00\x01\x00\x00\x00\x00\x03\x00\x00" <le_entry_spp_1> <le_entry_rows_1> <le_entry_bytecount_1> "\x4a\x01\x0d\x00\x01\x00\x00\x00\x00\x01\x00\x00" "\x00\x00\x00\x00"
<le_nested_sub_ifd> ::= "\x0a\x00" <le_entry_width_1> <le_entry_height_1> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_gray> "\x11\x01\x04\x00\x01\x00\x00\x00\x01\x03\x00\x00" <le_entry_spp_1> <le_entry_rows_1> <le_entry_bytecount_1> "\x4a\x01\x0d\x00\x01\x00\x00\x00\x00\x02\x00\x00" "\x00\x00\x00\x00"
<le_nested_deep_ifd> ::= "\x09\x00" <le_entry_width_1> <le_entry_height_1> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_gray> "\x11\x01\x04\x00\x01\x00\x00\x00\x02\x03\x00\x00" <le_entry_spp_1> <le_entry_rows_1> <le_entry_bytecount_1> "\x00\x00\x00\x00"

# Rare and older attributes: obsolete CellWidth/CellLength, FillOrder,
# DocumentName, orientation, PlanarConfiguration, identity, and SampleFormat.
<classic_le_legacy> ::= "II\x2a\x00\x08\x00\x00\x00" <le_legacy_ifd> <padding_14> <document_value> <software_value> <artist_value> <host_value> <gray_sample>
<le_legacy_ifd> ::= "\x13\x00" <le_entry_width_1> <le_entry_height_1> <le_entry_bits_8> <le_entry_compression_none> <le_entry_photo_gray> "\x08\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00" "\x09\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00" <le_entry_fill_order> "\x0d\x01\x02\x00\x08\x00\x00\x00\x00\x01\x00\x00" "\x11\x01\x04\x00\x01\x00\x00\x00\x20\x01\x00\x00" <le_entry_orientation> <le_entry_spp_1> <le_entry_rows_1> <le_entry_bytecount_1> "\x1c\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00" "\x31\x01\x02\x00\x08\x00\x00\x00\x08\x01\x00\x00" "\x3b\x01\x02\x00\x08\x00\x00\x00\x10\x01\x00\x00" "\x3c\x01\x02\x00\x08\x00\x00\x00\x18\x01\x00\x00" "\x53\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00" "\x00\x00\x00\x00"
<document_value> ::= <document_text> "\x00"
<document_text> ::= "DOC0001" | "ARCHIVE" | "PREVIEW"
<artist_value> ::= <artist_text> "\x00"
<artist_text> ::= "UNKNOWN" | "ANON001" | "ARTIST7"
<host_value> ::= <host_text> "\x00"
<host_text> ::= "HOST001" | "SCANNER" | "CAMERA1"
<le_entry_fill_order> ::= "\x0a\x01\x03\x00\x01\x00\x00\x00" <le_short_1_or_2_inline>
<le_entry_orientation> ::= "\x12\x01\x03\x00\x01\x00\x00\x00" <le_orientation_inline>
<le_short_1_or_2_inline> ::= "\x01\x00\x00\x00" | "\x02\x00\x00\x00"
<le_orientation_inline> ::= "\x01\x00\x00\x00" | "\x02\x00\x00\x00" | "\x03\x00\x00\x00" | "\x04\x00\x00\x00" | "\x05\x00\x00\x00" | "\x06\x00\x00\x00" | "\x07\x00\x00\x00" | "\x08\x00\x00\x00"

# BigTIFF v43: 8-byte offsets/counts and LONG8 strip fields.
<bigtiff_le> ::= "II\x2b\x00\x08\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00" <bigtiff_ifd> <padding_44> <gray_sample>
<bigtiff_ifd> ::= "\x09\x00\x00\x00\x00\x00\x00\x00" "\x00\x01\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x01\x01\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x02\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00" "\x03\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x06\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x11\x01\x10\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" "\x15\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x16\x01\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x17\x01\x10\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00"

# Reusable classic little-endian IFD entries (tag, type, count, inline value).
<le_entry_width_1> ::= "\x00\x01\x04\x00\x01\x00\x00\x00\x01\x00\x00\x00"
<le_entry_width_2> ::= "\x00\x01\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00"
<le_entry_width_4> ::= "\x00\x01\x04\x00\x01\x00\x00\x00\x04\x00\x00\x00"
<le_entry_height_1> ::= "\x01\x01\x04\x00\x01\x00\x00\x00\x01\x00\x00\x00"
<le_entry_height_2> ::= "\x01\x01\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00"
<le_entry_height_4> ::= "\x01\x01\x04\x00\x01\x00\x00\x00\x04\x00\x00\x00"
<le_entry_bits_8> ::= "\x02\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00"
<le_entry_compression_none> ::= "\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00"
<le_entry_photo_gray> ::= "\x06\x01\x03\x00\x01\x00\x00\x00" <le_gray_photo_inline>
<le_gray_photo_inline> ::= "\x00\x00\x00\x00" | "\x01\x00\x00\x00"
<le_entry_photo_rgb> ::= "\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00"
<le_entry_photo_palette> ::= "\x06\x01\x03\x00\x01\x00\x00\x00\x03\x00\x00\x00"
<le_entry_spp_1> ::= "\x15\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00"
<le_entry_spp_3> ::= "\x15\x01\x03\x00\x01\x00\x00\x00\x03\x00\x00\x00"
<le_entry_rows_1> ::= "\x16\x01\x04\x00\x01\x00\x00\x00\x01\x00\x00\x00"
<le_entry_rows_2> ::= "\x16\x01\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00"
<le_entry_bytecount_1> ::= "\x17\x01\x04\x00\x01\x00\x00\x00\x01\x00\x00\x00"
<le_entry_resolution_unit> ::= "\x28\x01\x03\x00\x01\x00\x00\x00" <le_resolution_unit_inline>
<le_resolution_unit_inline> ::= "\x01\x00\x00\x00" | "\x02\x00\x00\x00" | "\x03\x00\x00\x00"

<padding_14> ::= <zero>{14,14}
<padding_20> ::= <zero>{20,20}
<padding_44> ::= <zero>{44,44}
<padding_86> ::= <zero>{86,86}
<padding_122> ::= <zero>{122,122}
<padding_130> ::= <zero>{130,130}
<padding_142> ::= <zero>{142,142}
<zero> ::= "\x00"
<octet> ::= r'[\x00-\x7f]'
where len(str(<octet>)) == 1