Bug 702865: Don't walk through successive pages while linearising.
authorRobin Watts <[email protected]>
Thu, 24 Sep 2020 14:51:42 +0000 (15:51 +0100)
committerRobin Watts <[email protected]>
Thu, 24 Sep 2020 14:54:41 +0000 (15:54 +0100)
When preparing a document for linearisation, we walk all the sub
objects to mark those as being used by a given page.

Unfortunately, when we walk annotations, these can have 'Dest'
references that are other pages. The current code will attempt
to walk those too. This means we can recurse a very long way,
causing use to overflow the exception stack.

To avoid this we avoid stepping through references that take us
either to the Page tree or to other pages.

source/pdf/pdf-write.c

index 429fb5ec5007f03d58cb3833db61c2ca142cd9e1..a85e9398b6981528166cd458aec510a3cda00789 100644 (file)
@@ -997,11 +997,19 @@ mark_all(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, pdf_obj *val
 
                if (pdf_is_dict(ctx, val))
                {
-                       int i, n = pdf_dict_len(ctx, val);
+                       int i, n;
+                       n = pdf_dict_len(ctx, val);
 
                        for (i = 0; i < n; i++)
                        {
-                               mark_all(ctx, doc, opts, pdf_dict_get_val(ctx, val, i), flag, page);
+                               pdf_obj *v = pdf_dict_get_val(ctx, val, i);
+                               pdf_obj *type = pdf_dict_get(ctx, v, PDF_NAME(Type));
+
+                               /* Don't walk through the Page tree, or direct to a page. */
+                               if (pdf_name_eq(ctx, PDF_NAME(Pages), type) || pdf_name_eq(ctx, PDF_NAME(Page), type))
+                                       continue;
+
+                               mark_all(ctx, doc, opts, v, flag, page);
                        }
                }
                else if (pdf_is_array(ctx, val))
@@ -1010,7 +1018,14 @@ mark_all(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, pdf_obj *val
 
                        for (i = 0; i < n; i++)
                        {
-                               mark_all(ctx, doc, opts, pdf_array_get(ctx, val, i), flag, page);
+                               pdf_obj *v = pdf_array_get(ctx, val, i);
+                               pdf_obj *type = pdf_dict_get(ctx, v, PDF_NAME(Type));
+
+                               /* Don't walk through the Page tree, or direct to a page. */
+                               if (pdf_name_eq(ctx, PDF_NAME(Pages), type) || pdf_name_eq(ctx, PDF_NAME(Page), type))
+                                       continue;
+
+                               mark_all(ctx, doc, opts, v, flag, page);
                        }
                }
        }