~mcf/mupdf

ea5f445b6e9a86451d1dbf29c5ccfa199d9c8c26 — Robin Watts 9 months ago e626a51
Bug 701640: Fix linearisation offset problem.

When linearising, we write objects out in one pass to establish offsets.
We then create the hint objects, and do another pass to properly
write the file out.

During the first pass, we were creating a hint object without a
stream. The stream was then created before the second pass was
performed. Accordingly, the overall length of that object changes.
The code allowed for the change in the size of the stream, but
was failing to allow for it changing from not having a stream at all
to having a stream. (i.e. it allowed for the stream changing size,
but did not allow for the addition of "stream\n" and "endstream\n".)

Due to the 'slack' inherent in writing objects with default large
numbers in the first pass, and those numbers being reduced to smaller
values in the second pass, we were getting away with this in most
cases. The addition of an ASCIIHexDecode filter was tipping us over
the edge.

The fix is simply to ensure we create the object with a stream to
start with.
1 files changed, 8 insertions(+), 1 deletions(-)

M source/pdf/pdf-write.c
M source/pdf/pdf-write.c => source/pdf/pdf-write.c +8 -1
@@ 1237,6 1237,8 @@ add_linearization_objs(fz_context *ctx, pdf_document *doc, pdf_write_state *opts

	fz_try(ctx)
	{
		pdf_xref_entry *xe;

		/* Linearization params */
		params_obj = pdf_new_dict(ctx, doc, 10);
		params_ref = pdf_add_object(ctx, doc, params_obj);


@@ 1287,7 1289,12 @@ add_linearization_objs(fz_context *ctx, pdf_document *doc, pdf_write_state *opts
		pdf_dict_put(ctx, hint_obj, PDF_NAME(Filter), PDF_NAME(FlateDecode));
		opts->hints_length = pdf_new_int(ctx, INT_MIN);
		pdf_dict_put(ctx, hint_obj, PDF_NAME(Length), opts->hints_length);
		pdf_get_xref_entry(ctx, doc, hint_num)->stm_ofs = 0;
		xe = pdf_get_xref_entry(ctx, doc, hint_num);
		xe->stm_ofs = 0;
		/* Empty stream, required so that we write the object as
		 * a stream during the first pass. Without this, offsets
		 * for the xref will be wrong. */
		xe->stm_buf = fz_new_buffer(ctx, 1);
	}
	fz_always(ctx)
	{