Skip to content

Commit cdce87d

Browse files
author
Alexander Pliushchou
committed
Fix null pointer exception when reading stream object
DEVSIX-8301 DEVSIX-8374
1 parent 7934942 commit cdce87d

File tree

5 files changed

+99
-0
lines changed

5 files changed

+99
-0
lines changed

kernel/src/main/java/com/itextpdf/kernel/exceptions/KernelExceptionMessageConstant.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,10 @@ public final class KernelExceptionMessageConstant {
441441
public static final String XREF_HAS_AN_ENTRY_WITH_TOO_BIG_OFFSET = "Pdf document is to large to "
442442
+ "use normal cross reference table. Use cross reference streams instead. To enable feature use com.itextpdf"
443443
+ ".kernel.pdf.WriterProperties#setFullCompressionMode(true). ";
444+
public static final String UNABLE_TO_READ_OBJECT_STREAM ="Unable to read object stream.";
445+
public static final String UNABLE_TO_READ_STREAM_BYTES ="Unable to read stream bytes because stream is null.";
446+
public static final String INVALID_OBJECT_STREAM_NUMBER = "Unable to read object {0} with object stream " +
447+
"number {1} and index {2} from object stream.";
444448

445449
private KernelExceptionMessageConstant() {
446450
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,10 @@ public byte[] readStreamBytes(PdfStream stream, boolean decode) throws IOExcepti
380380
* @throws IOException on error.
381381
*/
382382
public byte[] readStreamBytesRaw(PdfStream stream) throws IOException {
383+
if (stream == null) {
384+
throw new PdfException(KernelExceptionMessageConstant.UNABLE_TO_READ_STREAM_BYTES);
385+
}
386+
383387
PdfName type = stream.getAsName(PdfName.Type);
384388
if (!PdfName.XRef.equals(type) && !PdfName.ObjStm.equals(type)) {
385389
checkPdfStreamLength(stream);
@@ -765,6 +769,10 @@ protected void readPdf() throws IOException {
765769
}
766770

767771
protected void readObjectStream(PdfStream objectStream) throws IOException {
772+
if (objectStream == null) {
773+
throw new PdfException(KernelExceptionMessageConstant.UNABLE_TO_READ_OBJECT_STREAM);
774+
}
775+
768776
int objectStreamNumber = objectStream.getIndirectReference().getObjNumber();
769777
int first = objectStream.getAsNumber(PdfName.First).intValue();
770778
int n = objectStream.getAsNumber(PdfName.N).intValue();
@@ -1457,6 +1465,12 @@ private PdfObject readObject(PdfIndirectReference reference, boolean fixXref) {
14571465
if (reference.getObjStreamNumber() > 0) {
14581466
PdfStream objectStream = (PdfStream) pdfDocument.getXref().
14591467
get(reference.getObjStreamNumber()).getRefersTo(false);
1468+
if (objectStream == null) {
1469+
throw new PdfException(MessageFormatUtil.format(
1470+
KernelExceptionMessageConstant.INVALID_OBJECT_STREAM_NUMBER, reference.getObjNumber()
1471+
, reference.getObjStreamNumber(), reference.getIndex()));
1472+
}
1473+
14601474
readObjectStream(objectStream);
14611475
return reference.refersTo;
14621476
} else if (reference.getOffset() > 0) {

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,36 @@ public void newPdfReaderConstructorPropertiesTest() throws IOException {
28142814
Assert.assertEquals(PdfObject.STREAM, pdfDoc.getPdfObject(5).getType());
28152815
}
28162816

2817+
@Test
2818+
public void streamObjIsNullTest() throws IOException {
2819+
ByteArrayOutputStream bsaos = new ByteArrayOutputStream();
2820+
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(bsaos));
2821+
2822+
new PdfDictionary().makeIndirect(pdfDocument);
2823+
2824+
PdfStream pdfDictionary = new PdfStream();
2825+
pdfDictionary.makeIndirect(pdfDocument);
2826+
2827+
int objNumber = pdfDictionary.getIndirectReference().objNr;
2828+
pdfDocument.catalog.getPdfObject().put(PdfName.StructTreeRoot, pdfDictionary);
2829+
pdfDocument.close();
2830+
2831+
PdfReader pdfReader = new PdfReader(new ByteArrayInputStream(bsaos.toByteArray())) {
2832+
@Override
2833+
protected PdfObject readObject(PdfIndirectReference reference) {
2834+
if (reference.objNr == objNumber) {
2835+
reference.setObjStreamNumber(objNumber - 1);
2836+
reference.setIndex(492);
2837+
}
2838+
return super.readObject(reference);
2839+
}
2840+
};
2841+
2842+
Exception e = Assert.assertThrows(PdfException.class, () -> new PdfDocument(pdfReader));
2843+
Assert.assertEquals(MessageFormatUtil.format(
2844+
KernelExceptionMessageConstant.INVALID_OBJECT_STREAM_NUMBER, 5, 4, 492), e.getMessage());
2845+
}
2846+
28172847
@Test
28182848
public void initTagTreeStructureThrowsOOMIsCatched() throws IOException {
28192849
File file = new File(SOURCE_FOLDER+ "big_table_lot_of_mcrs.pdf");
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.itextpdf.kernel.pdf;
2+
3+
import com.itextpdf.commons.utils.MessageFormatUtil;
4+
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
5+
import com.itextpdf.kernel.exceptions.PdfException;
6+
import com.itextpdf.test.ExtendedITextTest;
7+
import com.itextpdf.test.annotations.type.UnitTest;
8+
import org.junit.Assert;
9+
import org.junit.Test;
10+
import org.junit.experimental.categories.Category;
11+
12+
@Category(UnitTest.class)
13+
public class PdfReaderUnitTest extends ExtendedITextTest {
14+
15+
private static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/kernel/pdf/PdfReaderUnitTest/";
16+
17+
@Test
18+
public void readStreamBytesRawNullStreamTest() throws java.io.IOException {
19+
PdfReader reader = new PdfReader(SOURCE_FOLDER + "testFile.pdf");
20+
Exception e = Assert.assertThrows(PdfException.class, () -> reader.readStreamBytesRaw(null));
21+
Assert.assertEquals(KernelExceptionMessageConstant.UNABLE_TO_READ_STREAM_BYTES, e.getMessage());
22+
}
23+
24+
@Test
25+
public void readObjectStreamNullStreamTest() throws java.io.IOException {
26+
PdfReader reader = new PdfReader(SOURCE_FOLDER + "testFile.pdf");
27+
Exception e = Assert.assertThrows(PdfException.class, () -> reader.readObjectStream(null));
28+
Assert.assertEquals(KernelExceptionMessageConstant.UNABLE_TO_READ_OBJECT_STREAM, e.getMessage());
29+
}
30+
31+
@Test
32+
public void readObjectInvalidObjectStreamNumberTest() throws java.io.IOException {
33+
PdfReader reader = new PdfReader(SOURCE_FOLDER + "testFile.pdf");
34+
PdfDocument doc = new PdfDocument(reader);
35+
36+
PdfIndirectReference ref = new PdfIndirectReference(doc, 20);
37+
ref.setState(PdfObject.FREE);
38+
ref.setObjStreamNumber(5);
39+
ref.refersTo = null;
40+
41+
PdfIndirectReference ref2 = new PdfIndirectReference(doc, 5);
42+
ref2.setState(PdfObject.FREE);
43+
ref2.refersTo = null;
44+
doc.getXref().add(ref2);
45+
46+
doc.getCatalog().getPdfObject().put(PdfName.StructTreeRoot, ref);
47+
Exception e = Assert.assertThrows(PdfException.class, () -> reader.readObject(ref));
48+
Assert.assertEquals(MessageFormatUtil.format(
49+
KernelExceptionMessageConstant.INVALID_OBJECT_STREAM_NUMBER, 20, 5, 0), e.getMessage());
50+
}
51+
}
Binary file not shown.

0 commit comments

Comments
 (0)