Skip to content

Commit 84da047

Browse files
LodrKumquatiText-CI
authored andcommitted
Replace recursion with while-cycle in readXrefStream
DEVSIX-3048
1 parent 6b9a51a commit 84da047

File tree

2 files changed

+104
-104
lines changed

2 files changed

+104
-104
lines changed

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

Lines changed: 103 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -948,115 +948,118 @@ protected PdfDictionary readXrefSection() throws IOException {
948948
}
949949

950950
protected boolean readXrefStream(long ptr) throws IOException {
951-
tokens.seek(ptr);
952-
if (!tokens.nextToken()) {
953-
return false;
954-
}
955-
if (tokens.getTokenType() != PdfTokenizer.TokenType.Number) {
956-
return false;
957-
}
958-
if (!tokens.nextToken() || tokens.getTokenType() != PdfTokenizer.TokenType.Number) {
959-
return false;
960-
}
961-
if (!tokens.nextToken() || !tokens.tokenValueEqualsTo(PdfTokenizer.Obj)) {
962-
return false;
963-
}
964-
PdfXrefTable xref = pdfDocument.getXref();
965-
PdfObject object = readObject(false);
966-
PdfStream xrefStream;
967-
if (object.getType() == PdfObject.STREAM) {
968-
xrefStream = (PdfStream) object;
969-
if (!PdfName.XRef.equals(xrefStream.get(PdfName.Type))) {
951+
while (ptr != -1) {
952+
tokens.seek(ptr);
953+
if (!tokens.nextToken()) {
970954
return false;
971955
}
972-
} else {
973-
return false;
974-
}
975-
if (trailer == null) {
976-
trailer = new PdfDictionary();
977-
trailer.putAll(xrefStream);
978-
trailer.remove(PdfName.DecodeParms);
979-
trailer.remove(PdfName.Filter);
980-
trailer.remove(PdfName.Prev);
981-
trailer.remove(PdfName.Length);
982-
}
956+
if (tokens.getTokenType() != PdfTokenizer.TokenType.Number) {
957+
return false;
958+
}
959+
if (!tokens.nextToken() || tokens.getTokenType() != PdfTokenizer.TokenType.Number) {
960+
return false;
961+
}
962+
if (!tokens.nextToken() || !tokens.tokenValueEqualsTo(PdfTokenizer.Obj)) {
963+
return false;
964+
}
965+
PdfXrefTable xref = pdfDocument.getXref();
966+
PdfObject object = readObject(false);
967+
PdfStream xrefStream;
968+
if (object.getType() == PdfObject.STREAM) {
969+
xrefStream = (PdfStream) object;
970+
if (!PdfName.XRef.equals(xrefStream.get(PdfName.Type))) {
971+
return false;
972+
}
973+
} else {
974+
return false;
975+
}
976+
if (trailer == null) {
977+
trailer = new PdfDictionary();
978+
trailer.putAll(xrefStream);
979+
trailer.remove(PdfName.DecodeParms);
980+
trailer.remove(PdfName.Filter);
981+
trailer.remove(PdfName.Prev);
982+
trailer.remove(PdfName.Length);
983+
}
983984

984-
int size = ((PdfNumber) xrefStream.get(PdfName.Size)).intValue();
985-
PdfArray index;
986-
PdfObject obj = xrefStream.get(PdfName.Index);
987-
if (obj == null) {
988-
index = new PdfArray();
989-
index.add(new PdfNumber(0));
990-
index.add(new PdfNumber(size));
991-
} else {
992-
index = (PdfArray) obj;
993-
}
994-
PdfArray w = xrefStream.getAsArray(PdfName.W);
995-
long prev = -1;
996-
obj = xrefStream.get(PdfName.Prev);
997-
if (obj != null)
998-
prev = ((PdfNumber) obj).longValue();
999-
xref.setCapacity(size);
1000-
byte[] b = readStreamBytes(xrefStream, true);
1001-
int bptr = 0;
1002-
int[] wc = new int[3];
1003-
for (int k = 0; k < 3; ++k) {
1004-
wc[k] = w.getAsNumber(k).intValue();
1005-
}
1006-
for (int idx = 0; idx < index.size(); idx += 2) {
1007-
int start = index.getAsNumber(idx).intValue();
1008-
int length = index.getAsNumber(idx + 1).intValue();
1009-
xref.setCapacity(start + length);
1010-
while (length-- > 0) {
1011-
int type = 1;
1012-
if (wc[0] > 0) {
1013-
type = 0;
1014-
for (int k = 0; k < wc[0]; ++k) {
1015-
type = (type << 8) + (b[bptr++] & 0xff);
985+
int size = ((PdfNumber) xrefStream.get(PdfName.Size)).intValue();
986+
PdfArray index;
987+
PdfObject obj = xrefStream.get(PdfName.Index);
988+
if (obj == null) {
989+
index = new PdfArray();
990+
index.add(new PdfNumber(0));
991+
index.add(new PdfNumber(size));
992+
} else {
993+
index = (PdfArray) obj;
994+
}
995+
PdfArray w = xrefStream.getAsArray(PdfName.W);
996+
long prev = -1;
997+
obj = xrefStream.get(PdfName.Prev);
998+
if (obj != null)
999+
prev = ((PdfNumber) obj).longValue();
1000+
xref.setCapacity(size);
1001+
byte[] b = readStreamBytes(xrefStream, true);
1002+
int bptr = 0;
1003+
int[] wc = new int[3];
1004+
for (int k = 0; k < 3; ++k) {
1005+
wc[k] = w.getAsNumber(k).intValue();
1006+
}
1007+
for (int idx = 0; idx < index.size(); idx += 2) {
1008+
int start = index.getAsNumber(idx).intValue();
1009+
int length = index.getAsNumber(idx + 1).intValue();
1010+
xref.setCapacity(start + length);
1011+
while (length-- > 0) {
1012+
int type = 1;
1013+
if (wc[0] > 0) {
1014+
type = 0;
1015+
for (int k = 0; k < wc[0]; ++k) {
1016+
type = (type << 8) + (b[bptr++] & 0xff);
1017+
}
1018+
}
1019+
long field2 = 0;
1020+
for (int k = 0; k < wc[1]; ++k) {
1021+
field2 = (field2 << 8) + (b[bptr++] & 0xff);
1022+
}
1023+
int field3 = 0;
1024+
for (int k = 0; k < wc[2]; ++k) {
1025+
field3 = (field3 << 8) + (b[bptr++] & 0xff);
1026+
}
1027+
int base = start;
1028+
PdfIndirectReference newReference;
1029+
switch (type) {
1030+
case 0:
1031+
newReference = (PdfIndirectReference) new PdfIndirectReference(pdfDocument, base, field3, field2).setState(PdfObject.FREE);
1032+
break;
1033+
case 1:
1034+
newReference = new PdfIndirectReference(pdfDocument, base, field3, field2);
1035+
break;
1036+
case 2:
1037+
newReference = new PdfIndirectReference(pdfDocument, base, 0, field3);
1038+
newReference.setObjStreamNumber((int) field2);
1039+
break;
1040+
default:
1041+
throw new PdfException(PdfException.InvalidXrefStream);
10161042
}
1017-
}
1018-
long field2 = 0;
1019-
for (int k = 0; k < wc[1]; ++k) {
1020-
field2 = (field2 << 8) + (b[bptr++] & 0xff);
1021-
}
1022-
int field3 = 0;
1023-
for (int k = 0; k < wc[2]; ++k) {
1024-
field3 = (field3 << 8) + (b[bptr++] & 0xff);
1025-
}
1026-
int base = start;
1027-
PdfIndirectReference newReference;
1028-
switch (type) {
1029-
case 0:
1030-
newReference = (PdfIndirectReference) new PdfIndirectReference(pdfDocument, base, field3, field2).setState(PdfObject.FREE);
1031-
break;
1032-
case 1:
1033-
newReference = new PdfIndirectReference(pdfDocument, base, field3, field2);
1034-
break;
1035-
case 2:
1036-
newReference = new PdfIndirectReference(pdfDocument, base, 0, field3);
1037-
newReference.setObjStreamNumber((int) field2);
1038-
break;
1039-
default:
1040-
throw new PdfException(PdfException.InvalidXrefStream);
1041-
}
10421043

1043-
PdfIndirectReference reference = xref.get(base);
1044-
boolean refReadingState = reference != null && reference.checkState(PdfObject.READING) && reference.getGenNumber() == newReference.getGenNumber();
1045-
// for references that are added by xref table itself (like 0 entry)
1046-
boolean refFirstEncountered = reference == null
1047-
|| !refReadingState && reference.getDocument() == null;
1044+
PdfIndirectReference reference = xref.get(base);
1045+
boolean refReadingState = reference != null && reference.checkState(PdfObject.READING) && reference.getGenNumber() == newReference.getGenNumber();
1046+
// for references that are added by xref table itself (like 0 entry)
1047+
boolean refFirstEncountered = reference == null
1048+
|| !refReadingState && reference.getDocument() == null;
10481049

1049-
if (refFirstEncountered) {
1050-
xref.add(newReference);
1051-
} else if (refReadingState) {
1052-
reference.setOffset(newReference.getOffset());
1053-
reference.setObjStreamNumber(newReference.getObjStreamNumber());
1054-
reference.clearState(PdfObject.READING);
1050+
if (refFirstEncountered) {
1051+
xref.add(newReference);
1052+
} else if (refReadingState) {
1053+
reference.setOffset(newReference.getOffset());
1054+
reference.setObjStreamNumber(newReference.getObjStreamNumber());
1055+
reference.clearState(PdfObject.READING);
1056+
}
1057+
++start;
10551058
}
1056-
++start;
10571059
}
1060+
ptr = prev;
10581061
}
1059-
return prev == -1 || readXrefStream(prev);
1062+
return true;
10601063
}
10611064

10621065
protected void fixXref() throws IOException {

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,13 +1718,10 @@ public void testFileIsNotLockedOnException() throws IOException {
17181718
Assert.assertTrue(exceptionThrown);
17191719
}
17201720

1721-
@Ignore("DEVSIX-3048")
1721+
17221722
@Test
17231723
public void testManyAppendModeUpdates() throws Exception {
1724-
junitExpectedException.expect(java.lang.StackOverflowError.class);
1725-
17261724
String file = sourceFolder + "manyAppendModeUpdates.pdf";
1727-
17281725
PdfReader reader = new PdfReader(file);
17291726
PdfDocument document = new PdfDocument(reader);
17301727
document.close();

0 commit comments

Comments
 (0)