IndexOutOfBoundsException in PdfReader
Describe the bug
java.lang.IndexOutOfBoundsException: Index 57407 out of bounds for length 899
at java.util.ArrayList.get
at com.lowagie.text.pdf.PdfReader.readDocObj(PdfReader.java:1957)
at com.lowagie.text.pdf.PdfReader.<init>
Root cause: The full stack shows the exception originates inside the OpenPDF library.
57407 is a PDF object number and 899 the parsed-object-list size — the classic signature of a broken PDF cross-reference table. Invoice.writePdf merges each invoice attachment's stored bytes, and PdfDocument.write re-parses each with OpenPDF's PdfReader. One attachment on this invoice is a corrupt/malformed PDF whose xref points at object 57407 while only 899 exist → the legacy reader throws a raw IndexOutOfBoundsException instead of a clean parse error.
Preview of a preliminary project invoice. Single occurrence for this exact stack signature in the retained window; deterministic for the one corrupt attachment, no loop / no data corruption / no retry-storm. Company & user details withheld here per sensitive-data policy.
Fails only the one request, but blocks every PDF render of that invoice (preview/print/likely send) until the bad attachment is removed. Same class recurs for any invoice carrying a corrupt PDF attachment.
Master branch:
https://github.com/LibrePDF/OpenPDF/blob/master/openpdf-core/src/main/java/org/openpdf/text/pdf/PdfReader.java#L1965
2.0.3 version:
https://github.com/LibrePDF/OpenPDF/blob/2.0.3/openpdf/src/main/java/com/lowagie/text/pdf/PdfReader.java#L1957
Summary of the report: IndexOutOfBoundsException in PdfReader when parsing a PDF with a corrupt/malformed cross-reference (xref) stream — an object number referenced by the xref stream exceeds the size of the parsed object list.
What I verified in the current code (openpdf-core/src/main/java/org/openpdf/text/pdf/PdfReader.java):
- readXrefStream (~line 2294-2318): when parsing a cross-reference stream (type 2 entries, i.e. compressed objects living inside an object stream), it reads field2 — the object number of the containing object stream — directly from stream bytes and stores it as a key in objStmMark via objStmMark.put(on, seq). This value is never bounds-checked against the actual parsed object count; ensureXrefSize is only called for start/length (the compressed object's own number), not for field2.
- readDocObj (line 1965):
readObjStm((PRStream) xrefObj.get(n), h);
- n comes straight from an objStmMark key — no range check before calling .get(n).
- Contrast with getPdfObject(int idx) (line 1738-1744), just ~200 lines above, which does the correct thing:
if (idx < 0 || idx >= xrefObj.size()) {
return null;
}
That inconsistency is exactly the bug: one accessor validates bounds, the other doesn't, and a malformed/corrupt xref stream can point at an object number (e.g. 57407) far beyond the actual object list size (e.g. 899), producing the raw ArrayList.get IndexOutOfBoundsException instead of a handled parse error.
Conclusion: Yes, still a valid, unfixed bug on master. It's a missing-bounds-check issue, not something masked by input sanitization elsewhere, and it also affects 2.0.3 as noted in the issue.
Fix would be small: add the same n < 0 || n >= xrefObj.size() guard at line 1965 (skip/log and continue rather than crash), and ideally validate field2 in readXrefStream before storing it in objStmMark.
System
- OS: Ubuntu Linux
- OpenPDF version: 2.0.3
Your real name
Andreas Røsdal
IndexOutOfBoundsException in PdfReader
Describe the bug
Root cause: The full stack shows the exception originates inside the OpenPDF library.
57407 is a PDF object number and 899 the parsed-object-list size — the classic signature of a broken PDF cross-reference table. Invoice.writePdf merges each invoice attachment's stored bytes, and PdfDocument.write re-parses each with OpenPDF's PdfReader. One attachment on this invoice is a corrupt/malformed PDF whose xref points at object 57407 while only 899 exist → the legacy reader throws a raw IndexOutOfBoundsException instead of a clean parse error.
Preview of a preliminary project invoice. Single occurrence for this exact stack signature in the retained window; deterministic for the one corrupt attachment, no loop / no data corruption / no retry-storm. Company & user details withheld here per sensitive-data policy.
Fails only the one request, but blocks every PDF render of that invoice (preview/print/likely send) until the bad attachment is removed. Same class recurs for any invoice carrying a corrupt PDF attachment.
Master branch:
https://github.com/LibrePDF/OpenPDF/blob/master/openpdf-core/src/main/java/org/openpdf/text/pdf/PdfReader.java#L1965
2.0.3 version:
https://github.com/LibrePDF/OpenPDF/blob/2.0.3/openpdf/src/main/java/com/lowagie/text/pdf/PdfReader.java#L1957
Summary of the report: IndexOutOfBoundsException in PdfReader when parsing a PDF with a corrupt/malformed cross-reference (xref) stream — an object number referenced by the xref stream exceeds the size of the parsed object list.
What I verified in the current code (openpdf-core/src/main/java/org/openpdf/text/pdf/PdfReader.java):
readObjStm((PRStream) xrefObj.get(n), h);
if (idx < 0 || idx >= xrefObj.size()) {
return null;
}
That inconsistency is exactly the bug: one accessor validates bounds, the other doesn't, and a malformed/corrupt xref stream can point at an object number (e.g. 57407) far beyond the actual object list size (e.g. 899), producing the raw ArrayList.get IndexOutOfBoundsException instead of a handled parse error.
Conclusion: Yes, still a valid, unfixed bug on master. It's a missing-bounds-check issue, not something masked by input sanitization elsewhere, and it also affects 2.0.3 as noted in the issue.
Fix would be small: add the same n < 0 || n >= xrefObj.size() guard at line 1965 (skip/log and continue rather than crash), and ideally validate field2 in readXrefStream before storing it in objStmMark.
System
Your real name
Andreas Røsdal