java-topology/defects/libpng-scan/CLEAN.md
russell@unturf.com bbc12a3ca6 libtiff+libpng: 5-MOAD scan; 1 defect / libpng CLEAN
libtiff-0001: TIFFReadDirectory + TIFFReadCustomDirectory both contain
identical O(D^2) nested loops to detect duplicate IFD tags (bugzilla 1994
dedup block, tif_dirread.c). Adversarial TIFF with D=65535 entries causes
~2.1B comparisons per IFD open. Fix: sorted seen-array with binary-search
insert, O(D log D). Java model confirms 37x at D=8000; asymptotic ~3900x
at D=65535.

libpng: all 5 MOADs CLEAN. add_one_chunk O(new*old) in pngset.c is bounded
by a ~30-entry fixed chunk list; chunk dedup during read uses a bitmask O(1).
2026-03-31 21:41:06 -04:00

1.7 KiB

libpng — 5-MOAD scan CLEAN

Date: 2026-03-31 Version scanned: pnggroup/libpng HEAD (depth=1)

MOAD-0001 (CWE-407)

No O(N^2) membership pattern confirmed at meaningful scale.

Candidates investigated:

  1. add_one_chunk in pngset.cpng_set_keep_unknown_chunks calls add_one_chunk in a for loop; add_one_chunk does a linear scan (for i=0..count). Pattern is O(new * old). However, our chunk_list is bounded to ~30 known PNG chunks total — the static chunks_to_ignore[] array has 24 entries. At this scale (max ~50 chunks ever), O(N^2) = O(2500) comparisons per call. Not a real-world performance issue. CLEAN.

  2. png_handle_as_unknown in png.c — linear scan through chunk_list for each incoming chunk. Called once per chunk during for(;;) read loop. O(C * L) where C = number of chunks in file, L = chunk_list length. Both are bounded by small fixed constants in practice. CLEAN.

  3. png_file_has_chunk duplicate detection — uses a bitmask (chunks field in png_struct). O(1) lookup. No defect.

  4. sPLT palette handling — each sPLT chunk is appended without dedup scan. No O(N^2) membership test. CLEAN.

MOAD-0002 (Intertangle)

libpng uses a per-stream png_struct instance for all state. No shared global mutable state between independent PNG streams. CLEAN.

MOAD-0003 (Leaked Context)

C library — no ThreadLocal or thread-scoped carrier. Each stream has its own png_struct. CLEAN.

MOAD-0004 (CWE-312 Logged Secret)

png_warning and png_error do not log file paths, URIs, or headers. No credential logging path found. CLEAN.

MOAD-0005 (Thundering Herd)

No cache get+null+compute+put pattern. Purely synchronous stream decoder with no internal caches. CLEAN.