Skip to content

Commit 7f0e110

Browse files
committed
Correctly rebuild cross refrence table when trailer is before objects
DEVSIX-6064
1 parent 29ffca1 commit 7f0e110

File tree

4 files changed

+184
-78
lines changed

4 files changed

+184
-78
lines changed

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

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,7 @@ protected void fixXref() throws IOException {
13071307
}
13081308
}
13091309

1310+
13101311
protected void rebuildXref() throws IOException {
13111312
xrefStm = false;
13121313
hybridXref = false;
@@ -1316,40 +1317,70 @@ protected void rebuildXref() throws IOException {
13161317
tokens.seek(0);
13171318
trailer = null;
13181319
ByteBuffer buffer = new ByteBuffer(24);
1319-
PdfTokenizer lineTokenizer =
1320-
new PdfTokenizer(new RandomAccessFileOrArray(new ReusableRandomAccessSource(buffer)));
1321-
for (; ; ) {
1322-
long pos = tokens.getPosition();
1323-
buffer.reset();
1320+
try (PdfTokenizer lineTokenizer = new PdfTokenizer(
1321+
new RandomAccessFileOrArray(new ReusableRandomAccessSource(buffer)))) {
1322+
Long trailerIndex = null;
13241323

1325-
// added boolean because of mailing list issue (17 Feb. 2014)
1326-
if (!tokens.readLineSegment(buffer, true))
1327-
break;
1328-
if (buffer.get(0) == 't') {
1329-
if (!PdfTokenizer.checkTrailer(buffer))
1330-
continue;
1331-
tokens.seek(pos);
1332-
tokens.nextToken();
1333-
pos = tokens.getPosition();
1334-
try {
1335-
PdfDictionary dic = (PdfDictionary) readObject(false);
1336-
if (dic.get(PdfName.Root, false) != null)
1337-
trailer = dic;
1338-
else
1339-
tokens.seek(pos);
1340-
} catch (Exception e) {
1341-
tokens.seek(pos);
1324+
for (; ; ) {
1325+
long pos = tokens.getPosition();
1326+
buffer.reset();
1327+
1328+
// added boolean because of mailing list issue (17 Feb. 2014)
1329+
if (!tokens.readLineSegment(buffer, true)) {
1330+
break;
13421331
}
1343-
} else if (buffer.get(0) >= '0' && buffer.get(0) <= '9') {
1344-
int[] obj = PdfTokenizer.checkObjectStart(lineTokenizer);
1345-
if (obj == null)
1346-
continue;
1347-
int num = obj[0];
1348-
int gen = obj[1];
1349-
if (xref.get(num) == null || xref.get(num).getGenNumber() <= gen) {
1350-
xref.add(new PdfIndirectReference(pdfDocument, num, gen, pos));
1332+
if (buffer.get(0) == 't') {
1333+
if (!PdfTokenizer.checkTrailer(buffer)) {
1334+
continue;
1335+
}
1336+
tokens.seek(pos);
1337+
tokens.nextToken();
1338+
pos = tokens.getPosition();
1339+
if (isCurrentObjectATrailer()) {
1340+
// if the pdf is linearized it is possible that the trailer has been read
1341+
// before the actual objects it refers to this causes the trailer to have
1342+
// objects in READING state that's why we keep track of the position of the
1343+
// trailer and then asign it when the whole pdf has been loaded
1344+
trailerIndex = pos;
1345+
} else {
1346+
tokens.seek(pos);
1347+
}
1348+
} else if (buffer.get(0) >= '0' && buffer.get(0) <= '9') {
1349+
int[] obj = PdfTokenizer.checkObjectStart(lineTokenizer);
1350+
if (obj == null) {
1351+
continue;
1352+
}
1353+
int num = obj[0];
1354+
int gen = obj[1];
1355+
if (xref.get(num) == null || xref.get(num).getGenNumber() <= gen) {
1356+
xref.add(new PdfIndirectReference(pdfDocument, num, gen, pos));
1357+
}
13511358
}
13521359
}
1360+
// now that the document has been read fully the underlying trailer references won't be
1361+
// in READING state when the pdf has been linearised now we can assign the trailer
1362+
// and it will have the right references
1363+
setTrailerFromTrailerIndex(trailerIndex);
1364+
}
1365+
}
1366+
1367+
private boolean isCurrentObjectATrailer() {
1368+
try {
1369+
final PdfDictionary dic = (PdfDictionary) readObject(false);
1370+
return dic.get(PdfName.Root, false) != null;
1371+
} catch (Exception e) {
1372+
return false;
1373+
}
1374+
}
1375+
1376+
private void setTrailerFromTrailerIndex(Long trailerIndex) throws IOException {
1377+
if (trailerIndex == null) {
1378+
throw new PdfException(KernelExceptionMessageConstant.TRAILER_NOT_FOUND);
1379+
}
1380+
tokens.seek((long)trailerIndex);
1381+
final PdfDictionary dic = (PdfDictionary) readObject(false);
1382+
if (dic.get(PdfName.Root, false) != null) {
1383+
trailer = dic;
13531384
}
13541385
if (trailer == null) {
13551386
throw new PdfException(KernelExceptionMessageConstant.TRAILER_NOT_FOUND);

0 commit comments

Comments
 (0)