You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+7-1Lines changed: 7 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,8 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Ver
6
6
7
7
## [Unreleased]
8
8
9
+
## [1.3.0] - 2026-07-07
10
+
9
11
### Added
10
12
11
13
- **BigTIFF write support, end to end** (`exif/write.go`, `format/tiff/relocate_bigtiff.go`, `write.go`, tasks #264/#270/#271): `exif.Encode` now natively encodes BigTIFF-sourced EXIF (`EXIF.BigTIFF == true`) with a 16-byte header, 20-byte IFD entries, and 64-bit offsets throughout (BigTIFF spec §2, Aware Systems/libtiff); `format/tiff`'s copy-and-relocate serialiser is now container-width-aware end to end (image-block enumeration, `SubIFDs` 0x014A relocation, and every raw-offset scan performed after encoding), so a standalone BigTIFF file relocates correctly on write; and the top-level `Write`/`WriteFile` no longer refuse BigTIFF sources with `ErrWriteNotSupported` — the root-package guard has been removed now that both layers are verified end-to-end against real BigTIFF corpus fixtures (LONG8/SLONG8/IFD8 strip/tile arrays, multi-level SubIFD chains, and the committed `BigTIFF_LE.tif`/`BigTIFF_BE.tif`/`big_cramps_{be,le}.tif` fixtures). Two new sentinel errors guard the encode path: `exif.ErrBigTIFFPointerOverflow` (a sub-IFD or thumbnail pointer — fixed by spec to a 4-byte EXIF LONG field regardless of container — would need an absolute offset that does not fit in 32 bits) and `exif.ErrBigTIFFEncodeSizeExceeded` (the encoded payload would exceed a documented, test-overridable 4 GiB sanity ceiling, since BigTIFF's 64-bit offsets have no implicit `MaxUint32` saturation the way classic TIFF's do). `exif.ErrBigTIFFEncodeNotSupported` is no longer returned by `Encode` under normal conditions and its doc comment now marks it **Deprecated**; it is retained only for API compatibility and may be removed in a future major release. `ErrWriteNotSupported` remains exported for any future format without a write path.
@@ -38,6 +40,8 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Ver
38
40
-**`writeTIFFHeader`/`writeIFD` panicked on a non-standard `binary.ByteOrder`** (#247, PERF-201-LOW): a non-comma-ok type assertion to `binary.AppendByteOrder` (introduced by the byte-order refactor in v1.2.0) panicked for any `binary.ByteOrder` implementation other than the two standard-library singletons. The assertion is now comma-ok with a `PutUint16`/`PutUint32` fallback; the little-/big-endian fast path is unchanged and remains zero-allocation.
39
41
-**IPTC `Encode` extended-length overflow**: a `Dataset.Value` longer than the 4-byte extended-length field can represent was silently truncated to its low 32 bits while every value byte was still written, desynchronising the encoded stream. `Encode` now rejects such values with `iptc.ErrDatasetValueTooLarge` (see Added) instead of emitting a wrapped length field.
40
42
-**TIFF SubIFD type-13 (`IFD`) misparsed as UTF8** (part of #270): `format/tiff`'s relocator trusted `exif.Parse`'s type-13 decoding for tag `0x014A` (`SubIFDs`), but CIPA DC-008-2023's EXIF-3.0 assignment of `TypeUTF8` to the same numeric code as the legacy TIFF-extension `IFD` type meant a SubIFD pointer array declared as type 13 was silently corrupted or dropped on write. The relocator now re-scans the raw bytes for this tag directly instead of trusting the parsed struct.
43
+
- **XMP array-typed property container-type round-trip fidelity, plus Dublin Core allowlist gaps** (#272/#273, `xmp/namespace.go`, `xmp/rdf.go`, `xmp/write.go`, `xmp/xmp.go`): `collectionType`/`isCollectionProperty` were two independently maintained switch statements that had already drifted out of sync, and recognised only 5 of the 11 array-typed `dc:` properties (`creator`, `subject`, `title`, `description`, `rights`); a single-value `Set(NSdc, "contributor", ...)` — and `date`/`language`/`publisher`/`relation`/`type` — previously emitted a bare scalar element instead of the `rdf:Bag`/`rdf:Seq` container required by ISO 16684-1 §7.5. Both switches are now consolidated into one spec-sourced `arrayProperties` table covering all 11 `dc:` properties plus every other array-typed property across `xmpMM`, `xmpRights`, `xmp`, `tiff`, `exif`, `photoshop`, `Iptc4xmpCore`, and `Iptc4xmpExt`. The same consolidation corrects `xmpMM:Ingredients`/`xmpMM:Pantry` — previously wrongly coded as ordered `Seq` — to the spec-correct unordered `Bag` (Adobe XMP Specification Part 2 §1.2.8), and adds the previously-missing `xmpMM:Versions` (`Seq`). More fundamentally, a plain `Parse` → (unrelated field write) → `Encode` round trip previously downgraded *any* array-typed property outside this table's namespace/name coverage to a bare scalar, because the spec table was the sole authority `Encode` consulted — violating this project's "existing metadata is preserved exactly" mandate for every namespace the table does not (and, being finite, never can) enumerate. `XMP` now records the RDF collection kind (`Seq`/`Bag`/`Alt`) actually observed at parse time in a new unexported `containerTypes` map, consulted first on `Encode`, falling back to the spec table only for properties with no parse-time record (i.e. newly `Set()`). As a side effect, this also fixes a single-item `rdf:Alt` property outside the table leaking its internal `"lang|value"` storage separator into the serialised output text.
44
+
-**XMP numeric character references admitted XML 1.0 forbidden code points** (#274, `xmp/rdf.go`): `decodeCharRef` accepted any numeric character reference (`&#N;` / `&#xHH;`) whose value was a legal Unicode scalar value, even when that value falls outside the XML 1.0 §2.2 `Char` production — the C0 control block other than TAB/LF/CR, and the two BMP non-characters U+FFFE/U+FFFF. For U+001E specifically — this library's own internal multi-value record separator — a crafted-but-parseable document containing `` could cause `Encode` to spuriously re-serialise a genuinely scalar/Simple property as an `rdf:Bag`. `decodeCharRef` now substitutes U+FFFD for any such forbidden code point, matching the identical policy `writeXMLEscaped` already applies on the output side, so parsing and serialisation are consistent in both directions.
41
45
-**BigTIFF write is now fully supported through the public API** (`write.go`, `exif/write.go`, `format/tiff/relocate.go`, `format/tiff/relocate_bigtiff.go`, #264/#270/#271) — see Added for the full description.
42
46
-**XMP encoder now always wraps array-typed properties in their RDF collection container** (`xmp/write.go`, `xmp/namespace.go`): `dc:creator`, `dc:subject`, `dc:description`, `dc:rights`, `dc:title`, and the `xmpMM` ordered-array set (`History`, `Ingredients`, `Pantry`) are now serialised as `<rdf:Seq>`/`<rdf:Bag>`/`<rdf:Alt>` even when they hold exactly one value, per ISO 16684-1 §7.5. Previously, a single-item array-typed property (e.g. the common case of `SetCaption`/`SetCreator` writing exactly one value) was serialised as a bare `<prefix:local>value</prefix:local>` element, which is only correct for Simple (Text) properties. Round-trip value correctness (via this library's own lenient parser) was unaffected, but the produced wire format did not conform to the formal Lang-Alt/array schema that other XMP consumers expect.
43
47
@@ -58,6 +62,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Ver
58
62
-**IPTC extended-length overflow closed** (`iptc.Encode`): a `Dataset.Value` too long for the 4-byte extended-length field to represent was previously truncated silently rather than rejected, which could desynchronise the encoded stream; `Encode` now returns `iptc.ErrDatasetValueTooLarge` (CWE-190).
59
63
-**BigTIFF encode size ceiling added** (`exif.ErrBigTIFFEncodeSizeExceeded`): BigTIFF's 64-bit offset fields have no natural saturation ceiling the way classic TIFF's 32-bit fields do; `Encode` now enforces an explicit, documented, test-overridable 4 GiB sanity ceiling on the total encoded size before allocating the output buffer, preventing a pathological `IFDEntry.Count` from directing an unbounded allocation (CWE-400).
60
64
-**INFO: `format/jpeg` 256 MiB aggregate size cap added** (#262): JPEG now enforces the same project-wide aggregate input cap as every other container format, closing a defense-in-depth gap — JPEG was the only container package without one. Per-APP-segment lengths were already 16-bit bounded, so this is a normalisation rather than a fix for a known amplification bug.
65
+
-**LOW: XMP numeric character references could carry XML 1.0 forbidden code points** (#274): a crafted document containing a numeric character reference to a C0 control code point (other than TAB/LF/CR) or a BMP non-character (U+FFFE/U+FFFF) — including this library's own internal `\x1e` multi-value sentinel byte — was decoded verbatim instead of being replaced, extending the existing C0 control-character filtering (#170/#171) to this parse path. `decodeCharRef` now applies the identical U+FFFD substitution policy already used on the output side (CWE-91).
61
66
62
67
## [1.2.0] - 2026-06-10
63
68
@@ -304,7 +309,8 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Ver
0 commit comments