Summary
libpng_oracle::decode returns pixels and IHDR fields only, and its warning callback is a no-op with png_set_benign_errors(png, 1). So when libpng rejects and drops an ancillary chunk — a bKGD whose length does not match the colour type, an sBIT entry past the depth, an index past the palette — the oracle cannot tell: the decode succeeds, the pixels match, and nothing records that the chunk was discarded.
PR #485 fixed the encoder emitting exactly such chunks (bKGD/sBIT shaped for the colour type the caller set rather than the one the race wrote). Its tests had to assert the emitted payload against libpng's acceptance rules transcribed from pngrutil.c, plus a libpng decode of the file — an exact-byte test standing in for the differential one the crate's authority row calls for.
Proposal
In tooling/libpng-oracle/src/lib.rs:
DecodedImage gains bkgd: Option<Vec<u8>> and sbit: Option<Vec<u8>>, read via png_get_bKGD / png_get_sBIT after png_read_info, serialised in the chunk's own byte layout so a test compares them to what the encoder wrote;
DecodedImage gains warnings: usize (or Vec<String>), counted in warn_callback — benign errors route through it under png_set_benign_errors, so a dropped chunk becomes observable as "libpng warned".
Then crates/gamut-png/tests/ancillary_colour_type.rs can assert decoded.bkgd == read_chunk(png, b"bKGD") and decoded.warnings == 0, which is the differential claim.
Why not in #485
tooling/libpng-oracle was outside that PR's manifest; the review finding was repaired with the strongest test constructible inside it, and this is the remainder.
Summary
libpng_oracle::decodereturns pixels and IHDR fields only, and its warning callback is a no-op withpng_set_benign_errors(png, 1). So when libpng rejects and drops an ancillary chunk — abKGDwhose length does not match the colour type, ansBITentry past the depth, an index past the palette — the oracle cannot tell: the decode succeeds, the pixels match, and nothing records that the chunk was discarded.PR #485 fixed the encoder emitting exactly such chunks (
bKGD/sBITshaped for the colour type the caller set rather than the one the race wrote). Its tests had to assert the emitted payload against libpng's acceptance rules transcribed frompngrutil.c, plus a libpng decode of the file — an exact-byte test standing in for the differential one the crate's authority row calls for.Proposal
In
tooling/libpng-oracle/src/lib.rs:DecodedImagegainsbkgd: Option<Vec<u8>>andsbit: Option<Vec<u8>>, read viapng_get_bKGD/png_get_sBITafterpng_read_info, serialised in the chunk's own byte layout so a test compares them to what the encoder wrote;DecodedImagegainswarnings: usize(orVec<String>), counted inwarn_callback— benign errors route through it underpng_set_benign_errors, so a dropped chunk becomes observable as "libpng warned".Then
crates/gamut-png/tests/ancillary_colour_type.rscan assertdecoded.bkgd == read_chunk(png, b"bKGD")anddecoded.warnings == 0, which is the differential claim.Why not in #485
tooling/libpng-oraclewas outside that PR's manifest; the review finding was repaired with the strongest test constructible inside it, and this is the remainder.