tiff/tiff-edge
version 1.0
TIFF with tiles, two pages, 1/4/8 bit samples, FillOrder 2 and rare field types
- 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-edge/tiff-edge.fan
Use it
fanbase install tiff-edge fandango fuzz -F tiff-edge -n 10
How it does
accepts 100%, covers 9.4%, 56/s. 1000 inputs, seed 1.
| Parser | Accepts | Version |
|---|---|---|
| ffmpeg | 100% | ffmpeg version 7.1.5-0+deb13u1 |
| imagemagick | 100% | Version: ImageMagick 7.1.1-43 Q16 x86_64 22550 |
| libtiff-cov | 100% | libtiff 4.7.2 |
| pillow | 100% | 12.3.0 |
| tiffinfo | 100% |
The spec says its files decode always: as expected.
libtiff-cov
- lines reached
- 9.4% of 14513
- real files reach
- 18.2%
- only the generated files
- 95 lines
- only the real files
- 1367 lines
Cite it
@software{fanbase_tiff_tiff_edge_1_0,
author = {{The Fandango Fuzzer Team}},
title = {Tagged Image File Format (tiff/tiff-edge), a Fandango input specification},
version = {1.0},
url = {https://github.com/fandango-fuzzer/fanbase},
note = {Fanbase registry, specs/tiff/tiff-edge/tiff-edge.fan, sha256 17186f8dcb1e},
}
Source
Source (257 lines)
# TIFF 6.0 with the less common parts: both byte orders, strips and tiles, a
# two page file, 1, 4 and 8 bit samples, FillOrder 2, and the DOUBLE and
# SRATIONAL types for SMin/SMaxSampleValue. Seven flavours, each with its own
# symbols; offsets and byte counts are tied to the real lengths with where
# clauses.
<start> ::= <rg_le> | <gs_le> | <pl_le> | <bl_le> | <be_le> | <tl_le> | <mp_le>
# Flavour 1: RGB, little-endian, strip storage, 8x8, RATIONAL resolution
<rg_le> ::= <rg_header> <rg_ifd> <rg_data>
<rg_header> ::= b'II' b'\x2a\x00' b'\x08\x00\x00\x00'
<rg_ifd> ::= b'\x0d\x00' \
b'\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x00\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x01\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x02\x01\x03\x00\x03\x00\x00\x00' <rg_off_bits> \
b'\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00' \
b'\x11\x01\x04\x00\x01\x00\x00\x00' <rg_off_strip> \
b'\x15\x01\x03\x00\x01\x00\x00\x00\x03\x00\x00\x00' \
b'\x16\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x17\x01\x04\x00\x01\x00\x00\x00\xc0\x00\x00\x00' \
b'\x1a\x01\x05\x00\x01\x00\x00\x00' <rg_off_xres> \
b'\x1b\x01\x05\x00\x01\x00\x00\x00' <rg_off_yres> \
b'\x28\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00' \
b'\x00\x00\x00\x00'
<rg_off_bits> ::= <byte>{4}
<rg_off_strip> ::= <byte>{4}
<rg_off_xres> ::= <byte>{4}
<rg_off_yres> ::= <byte>{4}
<rg_data> ::= <rg_bits> <rg_xres> <rg_yres> <rg_strip>
<rg_bits> ::= b'\x08\x00\x08\x00\x08\x00'
<rg_xres> ::= b'\x48\x00\x00\x00\x01\x00\x00\x00'
<rg_yres> ::= b'\x48\x00\x00\x00\x01\x00\x00\x00'
<rg_strip> ::= <byte>{192}
# Flavour 2: Grayscale, little-endian, ASCII + DOUBLE + SRATIONAL field types
<gs_le> ::= <gs_header> <gs_ifd> <gs_data>
<gs_header> ::= b'II' b'\x2a\x00' b'\x08\x00\x00\x00'
<gs_ifd> ::= b'\x11\x00' \
b'\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x00\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x01\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x02\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x06\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x0e\x01\x02\x00\x22\x00\x00\x00' <gs_off_desc> \
b'\x11\x01\x04\x00\x01\x00\x00\x00' <gs_off_strip> \
b'\x15\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x16\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x17\x01\x04\x00\x01\x00\x00\x00\x40\x00\x00\x00' \
b'\x1a\x01\x05\x00\x01\x00\x00\x00' <gs_off_xres> \
b'\x1b\x01\x05\x00\x01\x00\x00\x00' <gs_off_yres> \
b'\x31\x01\x02\x00\x0d\x00\x00\x00' <gs_off_sw> \
b'\x32\x01\x02\x00\x14\x00\x00\x00' <gs_off_dt> \
b'\x54\x01\x0c\x00\x01\x00\x00\x00' <gs_off_smin> \
b'\x55\x01\x0a\x00\x01\x00\x00\x00' <gs_off_smax> \
b'\x00\x00\x00\x00'
<gs_off_desc> ::= <byte>{4}
<gs_off_strip> ::= <byte>{4}
<gs_off_xres> ::= <byte>{4}
<gs_off_yres> ::= <byte>{4}
<gs_off_sw> ::= <byte>{4}
<gs_off_dt> ::= <byte>{4}
<gs_off_smin> ::= <byte>{4}
<gs_off_smax> ::= <byte>{4}
<gs_data> ::= <gs_desc> <gs_sw> <gs_dt> <gs_xres> <gs_yres> <gs_smin> <gs_smax> <gs_strip>
<gs_desc> ::= b'Fandango grayscale extreme sample\x00'
<gs_sw> ::= b'fan-tiff 1.0\x00'
<gs_dt> ::= b'2026:08:05 12:00:00\x00'
<gs_xres> ::= b'\x48\x00\x00\x00\x01\x00\x00\x00'
<gs_yres> ::= b'\x48\x00\x00\x00\x01\x00\x00\x00'
<gs_smin> ::= b'\x00\x00\x00\x00\x00\x00\x00\x00'
<gs_smax> ::= b'\xff\x00\x00\x00\x01\x00\x00\x00'
<gs_strip> ::= <byte>{64}
# Flavour 3: Palette-color, little-endian, 4-bit, ColorMap in data region
<pl_le> ::= <pl_header> <pl_ifd> <pl_data>
<pl_header> ::= b'II' b'\x2a\x00' b'\x08\x00\x00\x00'
<pl_ifd> ::= b'\x0b\x00' \
b'\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x00\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x01\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x02\x01\x03\x00\x01\x00\x00\x00\x04\x00\x00\x00' \
b'\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x06\x01\x03\x00\x01\x00\x00\x00\x03\x00\x00\x00' \
b'\x11\x01\x04\x00\x01\x00\x00\x00' <pl_off_strip> \
b'\x15\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x16\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x17\x01\x04\x00\x01\x00\x00\x00\x20\x00\x00\x00' \
b'\x40\x01\x03\x00\x30\x00\x00\x00' <pl_off_cmap> \
b'\x00\x00\x00\x00'
<pl_off_strip> ::= <byte>{4}
<pl_off_cmap> ::= <byte>{4}
<pl_data> ::= <pl_cmap> <pl_strip>
<pl_cmap> ::= <byte>{96}
<pl_strip> ::= <byte>{32}
# Flavour 4: Bilevel, little-endian, WhiteIsZero, deprecated FillOrder=2
<bl_le> ::= <bl_header> <bl_ifd> <bl_data>
<bl_header> ::= b'II' b'\x2a\x00' b'\x08\x00\x00\x00'
<bl_ifd> ::= b'\x0b\x00' \
b'\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x00\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x01\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x02\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x06\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x0a\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00' \
b'\x11\x01\x04\x00\x01\x00\x00\x00' <bl_off_strip> \
b'\x15\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x16\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x17\x01\x04\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x00\x00\x00\x00'
<bl_off_strip> ::= <byte>{4}
<bl_data> ::= <bl_strip>
<bl_strip> ::= <byte>{8}
# Flavour 5: Grayscale, big-endian (MM). SHORT values in high half of field.
<be_le> ::= <be_header> <be_ifd> <be_data>
<be_header> ::= b'MM' b'\x00\x2a' b'\x00\x00\x00\x08'
<be_ifd> ::= b'\x00\x0a' \
b'\x00\xfe\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00' \
b'\x01\x00\x00\x03\x00\x00\x00\x01\x00\x08\x00\x00' \
b'\x01\x01\x00\x03\x00\x00\x00\x01\x00\x08\x00\x00' \
b'\x01\x02\x00\x03\x00\x00\x00\x01\x00\x08\x00\x00' \
b'\x01\x03\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00' \
b'\x01\x06\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00' \
b'\x01\x11\x00\x04\x00\x00\x00\x01' <be_off_strip> \
b'\x01\x15\x00\x03\x00\x00\x00\x01\x00\x01\x00\x00' \
b'\x01\x16\x00\x03\x00\x00\x00\x01\x00\x08\x00\x00' \
b'\x01\x17\x00\x04\x00\x00\x00\x01\x00\x00\x00\x40' \
b'\x00\x00\x00\x00'
<be_off_strip> ::= <byte>{4}
<be_data> ::= <be_strip>
<be_strip> ::= <byte>{64}
# Flavour 6: RGB, little-endian, tiled storage (16x16 tile, 16px multiples)
<tl_le> ::= <tl_header> <tl_ifd> <tl_data>
<tl_header> ::= b'II' b'\x2a\x00' b'\x08\x00\x00\x00'
<tl_ifd> ::= b'\x0b\x00' \
b'\xfe\x00\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x00\x01\x03\x00\x01\x00\x00\x00\x10\x00\x00\x00' \
b'\x01\x01\x03\x00\x01\x00\x00\x00\x10\x00\x00\x00' \
b'\x02\x01\x03\x00\x03\x00\x00\x00' <tl_off_bits> \
b'\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x06\x01\x03\x00\x01\x00\x00\x00\x02\x00\x00\x00' \
b'\x15\x01\x03\x00\x01\x00\x00\x00\x03\x00\x00\x00' \
b'\x42\x01\x03\x00\x01\x00\x00\x00\x10\x00\x00\x00' \
b'\x43\x01\x03\x00\x01\x00\x00\x00\x10\x00\x00\x00' \
b'\x44\x01\x04\x00\x01\x00\x00\x00' <tl_off_tile> \
b'\x45\x01\x04\x00\x01\x00\x00\x00\x00\x03\x00\x00' \
b'\x00\x00\x00\x00'
<tl_off_bits> ::= <byte>{4}
<tl_off_tile> ::= <byte>{4}
<tl_data> ::= <tl_bits> <tl_tile>
<tl_bits> ::= b'\x08\x00\x08\x00\x08\x00'
<tl_tile> ::= <byte>{768}
# Flavour 7: multi-page, little-endian - two bilevel IFDs chained via next-ptr
<mp_le> ::= <mp_header> <mp_ifd0> <mp_data0> <mp_ifd1> <mp_data1>
<mp_header> ::= b'II' b'\x2a\x00' b'\x08\x00\x00\x00'
<mp_ifd0> ::= b'\x0a\x00' \
b'\xfe\x00\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00' \
b'\x00\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x01\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x02\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x06\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x11\x01\x04\x00\x01\x00\x00\x00' <mp_off_s0> \
b'\x15\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x16\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x17\x01\x04\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
<mp_next0>
<mp_ifd1> ::= b'\x0a\x00' \
b'\xfe\x00\x04\x00\x01\x00\x00\x00\x02\x00\x00\x00' \
b'\x00\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x01\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x02\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x03\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x06\x01\x03\x00\x01\x00\x00\x00\x00\x00\x00\x00' \
b'\x11\x01\x04\x00\x01\x00\x00\x00' <mp_off_s1> \
b'\x15\x01\x03\x00\x01\x00\x00\x00\x01\x00\x00\x00' \
b'\x16\x01\x03\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x17\x01\x04\x00\x01\x00\x00\x00\x08\x00\x00\x00' \
b'\x00\x00\x00\x00'
<mp_off_s0> ::= <byte>{4}
<mp_next0> ::= <byte>{4}
<mp_off_s1> ::= <byte>{4}
<mp_data0> ::= <byte>{8}
<mp_data1> ::= <byte>{8}
# Constraints: every offset / next-IFD pointer == actual serialized position
where <rg_off_bits> == (8 + len(bytes(<rg_ifd>))).to_bytes(4, 'little')
where <rg_off_xres> == (8 + len(bytes(<rg_ifd>)) + 6).to_bytes(4, 'little')
where <rg_off_yres> == (8 + len(bytes(<rg_ifd>)) + 14).to_bytes(4, 'little')
where <rg_off_strip> == (8 + len(bytes(<rg_ifd>)) + 22).to_bytes(4, 'little')
where <gs_off_desc> == (8 + len(bytes(<gs_ifd>))).to_bytes(4, 'little')
where <gs_off_sw> == (8 + len(bytes(<gs_ifd>)) + 34).to_bytes(4, 'little')
where <gs_off_dt> == (8 + len(bytes(<gs_ifd>)) + 47).to_bytes(4, 'little')
where <gs_off_xres> == (8 + len(bytes(<gs_ifd>)) + 67).to_bytes(4, 'little')
where <gs_off_yres> == (8 + len(bytes(<gs_ifd>)) + 75).to_bytes(4, 'little')
where <gs_off_smin> == (8 + len(bytes(<gs_ifd>)) + 83).to_bytes(4, 'little')
where <gs_off_smax> == (8 + len(bytes(<gs_ifd>)) + 91).to_bytes(4, 'little')
where <gs_off_strip> == (8 + len(bytes(<gs_ifd>)) + 99).to_bytes(4, 'little')
where <pl_off_cmap> == (8 + len(bytes(<pl_ifd>))).to_bytes(4, 'little')
where <pl_off_strip> == (8 + len(bytes(<pl_ifd>)) + 96).to_bytes(4, 'little')
where <bl_off_strip> == (8 + len(bytes(<bl_ifd>))).to_bytes(4, 'little')
where <be_off_strip> == (8 + len(bytes(<be_ifd>))).to_bytes(4, 'big')
where <tl_off_bits> == (8 + len(bytes(<tl_ifd>))).to_bytes(4, 'little')
where <tl_off_tile> == (8 + len(bytes(<tl_ifd>)) + 6).to_bytes(4, 'little')
where <mp_off_s0> == (8 + len(bytes(<mp_ifd0>))).to_bytes(4, 'little')
where <mp_next0> == (8 + len(bytes(<mp_ifd0>)) + len(bytes(<mp_data0>))).to_bytes(4, 'little')
where <mp_off_s1> == (8 + len(bytes(<mp_ifd0>)) + len(bytes(<mp_data0>)) + len(bytes(<mp_ifd1>))).to_bytes(4, 'little')