Skip to content

Commit 0ce2116

Browse files
committed
Fix ArrayIndexOutOfBoundsException while opening invalid document with huge object reference
DEVSIX-7948
1 parent 3516ec7 commit 0ce2116

File tree

4 files changed

+44
-13
lines changed

4 files changed

+44
-13
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ public void setMaxNumberOfElementsInXrefStructure(int maxNumberOfElementsInXrefS
204204
public void checkIfXrefStructureExceedsTheLimit(int requestedCapacity) {
205205
// Objects in xref structures are using 1-based indexes, so to store maxNumberOfElementsInXrefStructure
206206
// amount of elements we need maxNumberOfElementsInXrefStructure + 1 capacity.
207-
if (requestedCapacity - 1 > maxNumberOfElementsInXrefStructure) {
207+
if (requestedCapacity - 1 > maxNumberOfElementsInXrefStructure || requestedCapacity < 0) {
208208
throw new MemoryLimitsAwareException(KernelExceptionMessageConstant.XREF_STRUCTURE_SIZE_EXCEEDED_THE_LIMIT);
209209
}
210210
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ This file is part of the iText (R) project.
2727
import com.itextpdf.io.logs.IoLogMessageConstant;
2828
import com.itextpdf.io.source.ByteUtils;
2929
import com.itextpdf.kernel.actions.data.ITextCoreProductData;
30+
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
31+
import com.itextpdf.kernel.exceptions.PdfException;
3032

3133
import java.io.IOException;
3234
import java.util.ArrayList;
@@ -435,7 +437,7 @@ void initFreeReferencesList(PdfDocument pdfDocument) {
435437
// ensure zero object is free
436438
xref[0].setState(PdfObject.FREE);
437439
TreeSet<Integer> freeReferences = new TreeSet<>();
438-
for (int i = 1; i < size(); ++i) {
440+
for (int i = 1; i < size() && i < xref.length; ++i) {
439441
PdfIndirectReference ref = xref[i];
440442
if (ref == null || ref.isFree()) {
441443
freeReferences.add(i);

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

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@ This file is part of the iText (R) project.
2222
*/
2323
package com.itextpdf.kernel.pdf;
2424

25+
import com.itextpdf.io.logs.IoLogMessageConstant;
26+
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
27+
import com.itextpdf.kernel.exceptions.PdfException;
2528
import com.itextpdf.kernel.utils.CompareTool;
29+
import com.itextpdf.test.AssertUtil;
2630
import com.itextpdf.test.ExtendedITextTest;
31+
import com.itextpdf.test.LogLevelConstants;
32+
import com.itextpdf.test.annotations.LogMessage;
33+
import com.itextpdf.test.annotations.LogMessages;
2734
import com.itextpdf.test.annotations.type.IntegrationTest;
2835

36+
import java.io.ByteArrayOutputStream;
2937
import java.io.IOException;
30-
3138
import org.junit.AfterClass;
3239
import org.junit.Assert;
3340
import org.junit.BeforeClass;
@@ -37,23 +44,45 @@ This file is part of the iText (R) project.
3744
@Category(IntegrationTest.class)
3845
public class PdfXrefTableTest extends ExtendedITextTest {
3946

40-
public static final String sourceFolder = "./src/test/resources/com/itextpdf/kernel/pdf/PdfXrefTableTest/";
41-
public static final String destinationFolder = "./target/test/com/itextpdf/kernel/pdf/PdfXrefTableTest/";
47+
public static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/kernel/pdf/PdfXrefTableTest/";
48+
public static final String DESTINATION_FOLDER = "./target/test/com/itextpdf/kernel/pdf/PdfXrefTableTest/";
4249

4350
@BeforeClass
4451
public static void beforeClass() {
45-
createOrClearDestinationFolder(destinationFolder);
52+
createOrClearDestinationFolder(DESTINATION_FOLDER);
4653
}
4754

4855
@AfterClass
4956
public static void afterClass() {
50-
CompareTool.cleanup(destinationFolder);
57+
CompareTool.cleanup(DESTINATION_FOLDER);
58+
}
59+
60+
@Test
61+
@LogMessages(messages = {
62+
@LogMessage(messageTemplate = IoLogMessageConstant.XREF_ERROR_WHILE_READING_TABLE_WILL_BE_REBUILT, logLevel = LogLevelConstants.ERROR)
63+
})
64+
public void openInvalidDocWithHugeRefTest() {
65+
String inputFile = SOURCE_FOLDER + "invalidDocWithHugeRef.pdf";
66+
AssertUtil.doesNotThrow(() -> new PdfDocument(new PdfReader(inputFile)));
5167
}
52-
68+
69+
@Test
70+
@LogMessages(messages = {
71+
@LogMessage(messageTemplate = IoLogMessageConstant.XREF_ERROR_WHILE_READING_TABLE_WILL_BE_REBUILT, logLevel = LogLevelConstants.ERROR)
72+
})
73+
public void openWithWriterInvalidDocWithHugeRefTest() {
74+
String inputFile = SOURCE_FOLDER + "invalidDocWithHugeRef.pdf";
75+
ByteArrayOutputStream outputStream = new com.itextpdf.io.source.ByteArrayOutputStream();
76+
77+
Exception e = Assert.assertThrows(PdfException.class, () ->
78+
new PdfDocument(new PdfReader(inputFile), new PdfWriter(outputStream)));
79+
Assert.assertEquals(KernelExceptionMessageConstant.XREF_STRUCTURE_SIZE_EXCEEDED_THE_LIMIT, e.getMessage());
80+
}
81+
5382
@Test
5483
public void testCreateAndUpdateXMP() throws IOException {
55-
String created = destinationFolder + "testCreateAndUpdateXMP_create.pdf";
56-
String updated = destinationFolder + "testCreateAndUpdateXMP_update.pdf";
84+
String created = DESTINATION_FOLDER + "testCreateAndUpdateXMP_create.pdf";
85+
String updated = DESTINATION_FOLDER + "testCreateAndUpdateXMP_update.pdf";
5786
PdfDocument pdfDocument = new PdfDocument(CompareTool.createTestPdfWriter(created));
5887
pdfDocument.addNewPage();
5988

@@ -93,9 +122,9 @@ public void testCreateAndUpdateXMP() throws IOException {
93122

94123
@Test
95124
public void testCreateAndUpdateTwiceXMP() throws IOException {
96-
String created = destinationFolder + "testCreateAndUpdateTwiceXMP_create.pdf";
97-
String updated = destinationFolder + "testCreateAndUpdateTwiceXMP_update.pdf";
98-
String updatedAgain = destinationFolder + "testCreateAndUpdateTwiceXMP_updatedAgain.pdf";
125+
String created = DESTINATION_FOLDER + "testCreateAndUpdateTwiceXMP_create.pdf";
126+
String updated = DESTINATION_FOLDER + "testCreateAndUpdateTwiceXMP_update.pdf";
127+
String updatedAgain = DESTINATION_FOLDER + "testCreateAndUpdateTwiceXMP_updatedAgain.pdf";
99128
PdfDocument pdfDocument = new PdfDocument(CompareTool.createTestPdfWriter(created));
100129
pdfDocument.addNewPage();
101130

0 commit comments

Comments
 (0)