The document from the bug has three unsigned signature fields, each
with an appearance stream consisting of the empty string. Before this
commit only one would be visibly rendered, while the two others would
still be there but not have any visible appearance rendered.
The reason that the first unsigned signature field is visible is that
when loading annotations pdf_update_appearance() is called for that
field it detects that it has an appearance stream but according to
pdf_is_local_object() that it is not local, i.e. not synthesised by
MuPDF. This causes MuPDF to first create a local xref, then do local
synthesis for the signature field, which means that the generated
appearance stream ends up in the local xref. The reason for it to be
stored there is that it should not be considered a change to the
document that would make it to file if the document is saved.
When the second unsigned signature field is specified when calling
pdf_update_appearance() MuPDF will simiarly detect that it has an
appearance stream, but when checking whether this appearance is local
there is a local xref in force. The object entry corresponding to the
stream is checked whether it is marked 'f'ree. Since the object has
never been stored into the local xref the entry is marked 0 as in
unused. This causes pdf_is_local_object() to return true, which in
turn causes pdf_update_appearance() to deduce that the appearance is
local, i.e. synthesised by MuPDF, thus no local synthesis is
performed. This is incorrect.
pdf_is_local_object() should treat any used entries in the local
xref as being local, and any unused entries as being non-local. E.g.
entries marked 'n'ew, 'o'bject stream or 'f'ree should all be
considered local, only entries marked 0 should be considered to be
non-local. This commit fixes this issue.
/* Local xrefs only ever have 1 section, and it should be solid. */
sub = xref->subsec;
if (num >= sub->start && num < sub->start + sub->len)
- return sub->table[num - sub->start].type != 'f';
+ return sub->table[num - sub->start].type != 0;
return 0;
}