Skip to content

v0.6.2: two upstream syncs, and a Chinese README that caught up

Choose a tag to compare

@ivanusto ivanusto released this 03 Sep 02:58
· 11 commits to main since this release

Two upstream syncs, both of them a case of "this file was never read, and was reported clean anyway", plus a translation that had fallen three releases behind.

A PNG text chunk can no longer inflate without a bound

Ported from upstream #308. A decompressed zTXt/iTXt value is capped at 1 MiB. PNG text is metadata, not a document: a few hundred KB of crafted deflate expands to hundreds of megabytes, and the marker scan then concatenates the payload with the decoded text and copies it again.

The inflate here already had a 16 MiB ceiling, but hitting it was treated the way corrupt input is treated: return nothing, say nothing. That is the wrong answer to this chunk is too big to read. Nothing was scanned, so nothing can be ruled out.

  • inspectPng reports the chunk as not fully inspected instead of leaving it out of the findings.
  • stripPng drops it even in "keep non-AI metadata" mode: a chunk nobody could read is not a chunk anyone can vouch for.
  • In strip-all mode the or short-circuits before the inflate, exactly as upstream's does, so the action stays the plain one.

#308 changed one more thing in passing. decompressobj hands back what it decoded before the input ran out, where zlib.decompress raised on a truncated stream and the whole chunk went unscanned. So the inflate now separates the two failures it used to collapse: input that simply ends returns the partial text, input that is malformed still returns nothing. A generator name in the surviving prefix of an interrupted download is found now, and was not before.

A truncated ID3v2 tag is reported, and the audio survives it

Ported from upstream #201. An MP3 whose ID3v2 header declares more tag than the file holds used to fall straight through: the frame parser refused it, inspect reported no findings, clean reported no actions, and a file that was never read past its header came out labelled clean.

  • Inspect checks the declared length against the bytes that are there before parsing anything, reports the tag as truncated, and scans what did arrive for markers. A partial tag is reported as partial, not as absent.
  • Clean cannot trust the length either, so it drops everything up to the first valid MPEG frame header: sync word plus version, layer, bitrate, sample rate and emphasis, because two bytes that look like a sync word are not an audio frame. A file with no such header anywhere is preserved exactly as it was, rather than emptied in the name of cleaning it.
  • Keep mode changes none of this, upstream included: a tag that cannot be read cannot be filtered frame by frame.
  • Both drivers carry it, including the report on a WAV id3 chunk holding a truncated tag. The slice driver walks for the frame header in overlapping chunks rather than reading the file into memory.

The Traditional Chinese README caught up

README.zh-TW.md had its changelog frozen at v0.4.2, and parts of its body had drifted with it: two rows of the format table still described the uuid box as XMP's alone, and the development section was missing four parity files, the -rs flag and the slice feature. v0.5.0, v0.6.0, v0.6.1 and this release are in. Both module lists were also missing js/av_meta.js, which has been there since v0.4.0.

Not ported, on purpose

Recorded in scripts/upstream-sources.json rather than mirrored, because a page has no counterpart: #302's strength to intensity rename on the CtrlRegen and DiffusionPurification subprocess flags, #201's synthid_is_watermarked and SynthID verdict finding in inspect_image (needs a pixel scorer this port does not have), and the data parameter threaded into run_synthid_score and inspect_av to skip a read-back that never happens here.

Parity anchors

image_meta.py bd5d9f19f370 · av_meta.py f012ed17276c · text_unicode.py, score_stylometry.py, detect_gumbel.py and the common.py slice unchanged.

1042 tests against upstream 946e4fc, no skips. Twelve new parity fixtures and four behaviour tests; without the ports, 22 of the new cases fail.