Skip to main content
Skip table of contents

Fail-safe processing of Outlines without Parent link

 

As stipulated in the PDF specification, an outline item is required to have a parent link. The parent of a top-level item is the outline dictionary itself.

PDFs generated using iText conform exactly to the above requirement. iText's logic also expect PDFs being processed using iText products to adhere to the same rule.  However, some PDF processors break this rule by generating empty Parent directories, rather than including valid Parent links in their Outlines.

This has the result of iText throwing non-descriptive errors (a NPE, and in other cases entering into an endless loop) when performing operations like merging PDF or copying PDF pages.

In the iText 7.2.1 release iText ignores the Parent links in the PDF; instead, it follows the hierarchy implied by First links. By doing so, iText ensures that missing links to parent Outlines are added in resulting PDFs.

JAVA

JAVA

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.utils.PdfMerger;
import java.io.IOException;

public class FailSafeProcessOutlines {
    public static void main(String[] args) {
        new FailSafeProcessOutlines().mergeOutlines();
    }

    /**
     * Merges a PDF with a broken outline structure
     */
    public void mergeOutlines() {
        PdfDocument inputDoc = null;
        PdfDocument outputDoc = null;
        try {
            inputDoc = new PdfDocument(new PdfReader("infiniteLoopInOutlineStructure.pdf"));
            outputDoc = new PdfDocument(new PdfWriter("result.pdf"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        PdfMerger merger = new PdfMerger(outputDoc, false, true);
        merger.merge(inputDoc, 1, 2);
        merger.close();
    }
}


C#

C#
using iText.Kernel.Pdf;
using iText.Kernel.Utils;

namespace Release_7._2._1_examples
{
    internal class FailSafeProcessOutlines
    {
        public static void Main(string[] args)
        {
            new FailSafeProcessOutlines().MergeOutlines();
        }
        
        /**
         * Merges a PDF with a broken outline structure
         */
        public void MergeOutlines() 
        {
            using (var inputDoc = new PdfDocument(new PdfReader("infiniteLoopInOutlineStructure.pdf"))) 
            using (var outputDoc = new PdfDocument(new PdfWriter("result.pdf")))
            {
                PdfMerger merger = new PdfMerger(outputDoc, false, true);
                merger.Merge(inputDoc, 1, 2);
                merger.Close();
            }
        }
    }
}

In iText version 7.2.1 the above example will produce a correct PDF without errors, whereas in previous versions processing the attached PDF would result in an infinite loop, leading to an Out of memory error.


outlinesHaveInfiniteLoop.pdf

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.