Skip to content

Commit 58cadfc

Browse files
committed
Stop returning null when the PdfPagesTree is invalid
DEVSIX-7181
1 parent 8c9f88c commit 58cadfc

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfDocument.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,9 @@ public int getNumberOfPdfObjects() {
388388
*
389389
* @param pageNum page number.
390390
*
391-
* @return page by page number. may return {@code null} in case the page tree is broken
391+
* @return page by page number.
392+
*
393+
* @throws PdfException in case the page tree is broken
392394
*/
393395
public PdfPage getPage(int pageNum) {
394396
checkClosingStatus();

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfPagesTree.java

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ public PdfPagesTree(PdfCatalog pdfCatalog) {
8686
this.pages = new ArrayList<>();
8787
if (pdfCatalog.getPdfObject().containsKey(PdfName.Pages)) {
8888
PdfDictionary pages = pdfCatalog.getPdfObject().getAsDictionary(PdfName.Pages);
89-
if (pages == null)
89+
if (pages == null) {
9090
throw new PdfException(
9191
KernelExceptionMessageConstant.INVALID_PAGE_STRUCTURE_PAGES_MUST_BE_PDF_DICTIONARY);
92+
}
9293
this.root = new PdfPages(0, Integer.MAX_VALUE, pages, null);
9394
parents.add(this.root);
9495
for (int i = 0; i < this.root.getCount(); i++) {
@@ -107,6 +108,7 @@ public PdfPagesTree(PdfCatalog pdfCatalog) {
107108
* Returns the {@link PdfPage} at the specified position in this list.
108109
*
109110
* @param pageNum one-based index of the element to return
111+
*
110112
* @return the {@link PdfPage} at the specified position in this list
111113
*/
112114
public PdfPage getPage(int pageNum) {
@@ -135,13 +137,19 @@ public PdfPage getPage(int pageNum) {
135137
}
136138
pages.set(pageNum, pdfPage);
137139
}
140+
if (pdfPage == null) {
141+
throw new PdfException(
142+
MessageFormatUtil.format(IoLogMessageConstant.PAGE_TREE_IS_BROKEN_FAILED_TO_RETRIEVE_PAGE,
143+
pageNum + 1));
144+
}
138145
return pdfPage;
139146
}
140147

141148
/**
142149
* Returns the {@link PdfPage} by page's PdfDictionary.
143150
*
144151
* @param pageDictionary page's PdfDictionary
152+
*
145153
* @return the {@code PdfPage} object, that wraps {@code pageDictionary}.
146154
*/
147155
public PdfPage getPage(PdfDictionary pageDictionary) {
@@ -215,7 +223,6 @@ public void addPage(PdfPage pdfPage) {
215223
}
216224
}
217225

218-
219226
pdfPage.makeIndirect(document);
220227
pdfPages.addPage(pdfPage.getPdfObject());
221228
pdfPage.parentPages = pdfPages;
@@ -231,8 +238,9 @@ public void addPage(PdfPage pdfPage) {
231238
*/
232239
public void addPage(int index, PdfPage pdfPage) {
233240
--index;
234-
if (index > pageRefs.size())
241+
if (index > pageRefs.size()) {
235242
throw new IndexOutOfBoundsException("index");
243+
}
236244
if (index == pageRefs.size()) {
237245
addPage(pdfPage);
238246
return;
@@ -254,6 +262,7 @@ public void addPage(int index, PdfPage pdfPage) {
254262
* indices).
255263
*
256264
* @param pageNum the one-based index of the PdfPage to be removed
265+
*
257266
* @return the page that was removed from the list
258267
*/
259268
public PdfPage removePage(int pageNum) {
@@ -281,6 +290,7 @@ void releasePage(int pageNumber) {
281290
* Generate PdfPages tree.
282291
*
283292
* @return root {@link PdfPages}
293+
*
284294
* @throws PdfException in case empty document
285295
*/
286296
protected PdfObject generateTree() {
@@ -346,14 +356,15 @@ private void loadPage(int pageNum) {
346356
/**
347357
* Load page from pages tree node structure
348358
*
349-
* @param pageNum page number to load
359+
* @param pageNum page number to load
350360
* @param processedParents set with already processed parents object reference numbers
351-
* if this method was called recursively to avoid infinite recursion.
361+
* if this method was called recursively to avoid infinite recursion.
352362
*/
353363
private void loadPage(int pageNum, Set<PdfIndirectReference> processedParents) {
354364
PdfIndirectReference targetPage = pageRefs.get(pageNum);
355-
if (targetPage != null)
365+
if (targetPage != null) {
356366
return;
367+
}
357368

358369
//if we go here, we have to split PdfPages that contains pageNum
359370
int parentIndex = findPageParent(pageNum);
@@ -408,12 +419,16 @@ private void loadPage(int pageNum, Set<PdfIndirectReference> processedParents) {
408419
PdfPages lastPdfPages = null;
409420
for (int i = 0; i < kids.size() && kidsCount > 0; i++) {
410421
/*
411-
* We don't release pdfPagesObject in the end of each loop because we enter this for-cycle only when parent has PdfPages kids.
412-
* If all of the kids are PdfPages, then there's nothing to release, because we don't release PdfPages at this point.
422+
* We don't release pdfPagesObject in the end of each loop because we enter this for-cycle only when
423+
* parent has PdfPages kids.
424+
* If all of the kids are PdfPages, then there's nothing to release, because we don't release
425+
* PdfPages at this point.
413426
* If there are kids that are instances of PdfPage, then there's no sense in releasing them:
414-
* in this case ParentTreeStructure is being rebuilt by inserting an intermediate PdfPages between the parent and a PdfPage,
415-
* thus modifying the page object by resetting its parent, thus making it impossible to release the object.
416-
*/
427+
* in this case ParentTreeStructure is being rebuilt by inserting an intermediate PdfPages between
428+
* the parent and a PdfPage,
429+
* thus modifying the page object by resetting its parent, thus making it impossible to release the
430+
* object.
431+
*/
417432
PdfDictionary pdfPagesObject = kids.getAsDictionary(i);
418433
if (pdfPagesObject.getAsArray(PdfName.Kids) == null) {
419434
// pdfPagesObject is PdfPage

kernel/src/test/java/com/itextpdf/kernel/pdf/PdfPagesTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,8 +770,11 @@ public void testPageTreeGenerationWhenFirstPdfPagesHasOnePageOnly() {
770770
}
771771

772772
private static void findAndAssertNullPages(PdfDocument pdfDocument, Set<Integer> nullPages) {
773-
for (Integer e : nullPages) {
774-
Assert.assertNull(pdfDocument.getPage((int) e));
773+
for (Integer nullPage : nullPages) {
774+
int pageNum = (int)nullPage;
775+
Exception exception = Assert.assertThrows(PdfException.class,()-> pdfDocument.getPage(pageNum));
776+
Assert.assertEquals(exception.getMessage() , MessageFormatUtil.format(
777+
IoLogMessageConstant.PAGE_TREE_IS_BROKEN_FAILED_TO_RETRIEVE_PAGE, pageNum));
775778
}
776779
}
777780

0 commit comments

Comments
 (0)