From 5c5a13b31da451e47fe2df48aacf1d00377aaf64 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Thu, 29 Nov 2012 17:21:36 +0000 Subject: Bug 693290: Fix for potential infinite recursion reading xrefs. Fix an issue spotted by zeniko. The patch is slightly modified from his supplied one to avoid problems with repeated freeing of the buffer, and to avoid abusing fz_buffer, but is largely based on his work. Many thanks. --- pdf/pdf_xref.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'pdf') diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index 5182a263..4f19428d 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -422,8 +422,17 @@ pdf_read_xref(pdf_document *xref, int ofs, pdf_lexbuf *buf) return trailer; } +typedef struct ofs_list_s ofs_list; + +struct ofs_list_s +{ + int max; + int len; + int *list; +}; + static void -pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf) +do_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf, ofs_list *offsets) { pdf_obj *trailer = NULL; fz_context *ctx = xref->ctx; @@ -438,6 +447,25 @@ pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf) { do { + int i; + /* Avoid potential infinite recursion */ + for (i = 0; i < offsets->len; i ++) + { + if (offsets->list[i] == ofs) + break; + } + if (i < offsets->len) + { + fz_warn(ctx, "ignoring xref recursion with offset %d", ofs); + break; + } + if (offsets->len == offsets->max) + { + offsets->list = fz_resize_array(ctx, offsets->list, offsets->max*2, sizeof(int)); + offsets->max *= 2; + } + offsets->list[offsets->len++] = ofs; + trailer = pdf_read_xref(xref, ofs, buf); /* FIXME: do we overwrite free entries properly? */ @@ -452,7 +480,7 @@ pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf) /* We only recurse if we have both xrefstm and prev. * Hopefully this happens infrequently. */ if (xrefstmofs && prevofs) - pdf_read_xref_sections(xref, xrefstmofs, buf); + do_read_xref_sections(xref, xrefstmofs, buf, offsets); if (prevofs) ofs = prevofs; else if (xrefstmofs) @@ -469,6 +497,29 @@ pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf) } } +static void +pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf) +{ + fz_context *ctx = xref->ctx; + ofs_list list; + + list.len = 0; + list.max = 10; + list.list = fz_malloc_array(ctx, 10, sizeof(int)); + fz_try(ctx) + { + do_read_xref_sections(xref, ofs, buf, &list); + } + fz_always(ctx) + { + fz_free(ctx, list.list); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } +} + /* * load xref tables from pdf * -- cgit v1.2.3