Incremental updates and why they matter
ISO 32000-2 §7.5.6 Evidence: Standard-backed
At a glance
Section titled “At a glance”When a PDF changes after it is written, the safe way to save it is not to rewrite the file. Instead, you append the changed objects and a new cross-reference section to the end, leaving every original byte exactly where it was. This page explains how that works and why it is the reason a digital signature can survive a later edit.
Why this matters
Section titled “Why this matters”A signature protects a range of bytes. If saving a one-word change rewrote the file, every byte offset would move. The signed range would no longer describe the same content. The signature would break, even though the signed content itself was untouched.
Incremental updates exist so that does not happen. The original bytes, including the bytes a signature covers, stay put. A reviewer can take a signed-then-edited document and verify the first signature against the original revision. The reviewer sees precisely what was signed and, separately, what changed afterward. Get this wrong and you either invalidate good signatures or, worse, lose the ability to prove what a signature actually attested to.
The short version
Section titled “The short version”- An incremental update appends: new and changed objects, then a new cross-reference section, then a new trailer, all at the end of the file.
- The original file content is left intact — not edited in place.
- The new trailer carries a
/Preventry: the byte offset of the previous cross-reference section. The sections form a backward chain. - A reader builds its index by walking that chain newest-first. For any object number, the most recent entry wins.
- Because nothing was overwritten, the byte range an earlier signature covered is still byte-for-byte the same — so the signature still verifies, and you can recover the document exactly as it was signed.
How NextPDF approaches it
Section titled “How NextPDF approaches it”NextPDF writes the base document as described on the previous page, then exposes the three things an incremental update needs.
After build(), the writer (src/Writer/PdfWriter.php) keeps:
- the output buffer, retrievable via
getBuffer(), so an update can be appended to the exact end of the existing bytes; - the byte offset of the last cross-reference section, via
getLastXrefOffset(), which becomes the new section’s/Prevvalue; - the catalog dictionary entries, via
getCatalogEntries(), so an update that must re-emit the catalog (for example to attach a signature reference) does not lose any prior keys.
An appended revision allocates new object numbers (or reuses existing ones
for objects it replaces) against the same ObjectRegistry, so object
numbering stays consistent across revisions. The new cross-reference
section lists only the objects this revision touched. The new trailer
repeats the previous trailer’s entries and adds /Prev, pointing back at the
prior section. That chain is what a reader follows.
The clearest place this matters is signing. NextPDF’s
ByteRangeCalculator (src/Security/Signature/ByteRangeCalculator.php)
computes the /ByteRange array as two segments: everything before the
signature value, and everything after it — so the signature covers the
whole revision except its own bytes. Because a later edit is appended
rather than written over those bytes, that range never moves.
- Write base revision Header, body, xref section, trailer — the original bytes.
- Sign A /ByteRange digest covers the whole revision except the signature value itself.
- Edit and save Changed objects + a new xref section are appended; originals are untouched.
- New trailer chains back The appended trailer carries /Prev = offset of the previous xref section.
- Verify The first signature still covers the same unchanged bytes; the chain shows what came after.
What the evidence says
Section titled “What the evidence says”The append-only rule is normative. Spec: ISO 32000-2, §7.5.6 ISO 32000-2 §7.5.6 states that the contents of a PDF can be updated incrementally without rewriting the entire file, and that when doing so, changes shall be appended to the end of the file, leaving the original contents intact. Evidence: Standard-backed
The same clause defines the mechanics. A cross-reference section for an
incremental update contains entries only for objects that were changed,
replaced, or deleted. Deleted objects are left in the file but marked deleted
through their cross-reference entries. The added trailer shall
contain a /Prev entry giving the location of the previous cross-reference
section. The update’s entry for a changed object carries the byte offset of
the new copy, overriding the old offset. A reader builds its
cross-reference information so that the most recent copy of each object is
the one accessed.
The signature consequence is stated directly by
Spec: ISO 32000-2, §12.8.1 ISO 32000-2 §12.8.1 : a byte-range digest
is computed over a range of the file — normally the whole file, excluding
the signature value (the /Contents entry). The standard then notes that
if a signed document is modified and saved by incremental update, the data
corresponding to the original signature’s byte range is preserved, so if
the signature is valid the document’s state at signing time can be
recreated. Append-only is not a nicety. It is the property the signature
model depends on.
Practical example
Section titled “Practical example”A signed-then-edited PDF, viewed structurally. The original revision ends at
its own %%EOF. The second revision is appended below it.
%PDF-2.0... original objects, including the signature dictionary ...xref0 8... entries for the original revision ...trailer<< /Size 8 /Root 1 0 R >>startxref920%%EOF <-- end of revision 1: the signed bytes stop here9 0 obj <-- revision 2, appended<< /Type /Annot /Subtype /Text /Contents (added after signing) >>endobjxref0 19 0 obj-entry...8 90000001740 00000 ntrailer<< /Size 10 /Root 1 0 R /Prev 920 >>startxref1980%%EOFA validator reads the last trailer, sees /Prev 920, and now has the
whole chain. It can verify the signature against the bytes up to the first
%%EOF, which are unchanged. It can then report separately that revision 2
added an annotation. The history is in the file. Nothing was hidden by
overwriting.
Common misconception
Section titled “Common misconception”The trap is “incremental update means the change is small, so it is harmless.” Appending is about byte preservation, not size. An incremental update can add a great deal of content. What makes it an incremental update is that it does not touch the bytes that were already there. The corollary catches people too: a tool that “optimizes” or “linearizes” a signed PDF by rewriting it from scratch will produce a smaller, cleaner file and a broken signature, because the signed byte range no longer exists. Saving a signed PDF and re-saving it are not the same operation.
Limits and boundaries
Section titled “Limits and boundaries”Append-only protects the bytes. It does not, by itself, tell you whether the appended changes were authorised. A second revision can legitimately add a second signature, or it can add content the first signer never intended. Deciding which is the job of signature validation and modification-detection policy (DocMDP). Appending is the substrate that makes that analysis possible, not the analysis itself.
This page also does not cover how a signature’s two byte ranges are computed and stitched, nor what a complete validation checks. Those are separate topics. And the guarantee here is about files written and updated by a conforming writer: a file whose earlier revisions were already malformed does not become well-formed by being appended to.
Mini-FAQ
Section titled “Mini-FAQ”How do I know how many revisions a PDF has?
Count the %%EOF markers and follow the /Prev chain from the last
trailer. Each cross-reference section reached is one saved revision.
Does deleting an object remove it from the file? No. An incremental update marks the object deleted in its cross-reference entry, but the object’s bytes remain in earlier revisions. “Deleted” means “not referenced by the current revision,” not “erased.”
Can an incremental update change the PDF version?
Yes, by setting the /Version entry in the catalog in the appended
revision. The header stays as written. The catalog /Version takes
precedence when it names a later version.
Related docs
Section titled “Related docs”- What a PDF actually is — the object model and the single cross-reference section an update extends.
- How signatures sit in a PDF — the byte-range mechanism that incremental updates exist to protect.
- Validating a signature properly — what a correct validation checks across a file’s revision history.
Glossary
Section titled “Glossary”- Incremental update — saving a change by appending the changed objects, a new cross-reference section, and a new trailer to the end of the file, without altering existing bytes.
/Prev— the trailer (or cross-reference stream) entry holding the byte offset of the previous cross-reference section. It links revisions into a backward chain.- Revision — the file state captured by one cross-reference section and its trailer. A file with N cross-reference sections has N revisions.
/ByteRange— the array in a signature dictionary giving the two byte segments the signature digest covers (everything except the signature value itself).- Signed byte range — the exact bytes a signature’s digest was computed over. Incremental updates exist so these bytes are never moved or overwritten.