Fix for XRef stream parsing when last object not included (#399)

- xrefstream: Fix when Index too short. Instead of appending the number of objects appends higher than the maximum index. Fix object number for XRefs stream table when its own offset encountered. Test case included
This commit is contained in:
Gunnsteinn Hall 2019-04-10 21:26:35 +00:00 committed by GitHub
parent 80014220cd
commit ea91b30b1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 2 deletions

View File

@ -0,0 +1,46 @@
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.md', which is part of this source code package.
*/
package core
import (
"io/ioutil"
"testing"
"github.com/stretchr/testify/require"
)
func TestParseXRefs(t *testing.T) {
objData, err := ioutil.ReadFile("./testdata/obj94_xrefs")
require.NoError(t, err)
p := NewParserFromString(string(objData))
_, err = p.parseXrefStream(nil)
require.NoError(t, err)
expected := XrefTable{
17: {XType: 0, ObjectNumber: 17, Generation: 0, Offset: 427290, OsObjNumber: 0, OsObjIndex: 0},
55: {XType: 0, ObjectNumber: 55, Generation: 0, Offset: 427442, OsObjNumber: 0, OsObjIndex: 0},
79: {XType: 0, ObjectNumber: 79, Generation: 0, Offset: 427487, OsObjNumber: 0, OsObjIndex: 0},
80: {XType: 0, ObjectNumber: 80, Generation: 0, Offset: 427921, OsObjNumber: 0, OsObjIndex: 0},
81: {XType: 0, ObjectNumber: 81, Generation: 0, Offset: 428071, OsObjNumber: 0, OsObjIndex: 0},
82: {XType: 0, ObjectNumber: 82, Generation: 0, Offset: 429516, OsObjNumber: 0, OsObjIndex: 0},
83: {XType: 0, ObjectNumber: 83, Generation: 0, Offset: 429601, OsObjNumber: 0, OsObjIndex: 0},
84: {XType: 0, ObjectNumber: 84, Generation: 0, Offset: 429640, OsObjNumber: 0, OsObjIndex: 0},
85: {XType: 0, ObjectNumber: 85, Generation: 0, Offset: 429679, OsObjNumber: 0, OsObjIndex: 0},
86: {XType: 0, ObjectNumber: 86, Generation: 0, Offset: 429714, OsObjNumber: 0, OsObjIndex: 0},
87: {XType: 0, ObjectNumber: 87, Generation: 0, Offset: 429765, OsObjNumber: 0, OsObjIndex: 0},
88: {XType: 0, ObjectNumber: 88, Generation: 0, Offset: 429816, OsObjNumber: 0, OsObjIndex: 0},
89: {XType: 0, ObjectNumber: 89, Generation: 0, Offset: 429877, OsObjNumber: 0, OsObjIndex: 0},
90: {XType: 0, ObjectNumber: 90, Generation: 0, Offset: 429948, OsObjNumber: 0, OsObjIndex: 0},
91: {XType: 0, ObjectNumber: 91, Generation: 0, Offset: 430019, OsObjNumber: 0, OsObjIndex: 0},
92: {XType: 0, ObjectNumber: 92, Generation: 0, Offset: 430054, OsObjNumber: 0, OsObjIndex: 0},
// Additional object (not in index):
// Modified such that offset is 0 and number corrected.
94: {XType: 0, ObjectNumber: 94, Generation: 0, Offset: 0, OsObjNumber: 0, OsObjIndex: 0},
}
require.Equal(t, expected, p.xrefs)
}

View File

@ -840,6 +840,8 @@ func (parser *PdfParser) parseXrefStream(xstm *PdfObjectInteger) (*PdfObjectDict
parser.reader = bufio.NewReader(parser.rs)
}
xsOffset := parser.GetFileOffset()
xrefObj, err := parser.ParseIndirectObject()
if err != nil {
common.Log.Debug("ERROR: Failed to read xref object")
@ -967,8 +969,14 @@ func (parser *PdfParser) parseXrefStream(xstm *PdfObjectInteger) (*PdfObjectDict
if entries == objCount+1 {
// For compatibility, expand the object count.
common.Log.Debug("BAD file: allowing compatibility (append one object to xref stm)")
indexList = append(indexList, objCount)
common.Log.Debug("Incompatibility: Index missing coverage of 1 object - appending one - May lead to problems")
maxIndex := objCount - 1
for _, ind := range indexList {
if ind > maxIndex {
maxIndex = ind
}
}
indexList = append(indexList, maxIndex+1)
objCount++
}
@ -1040,6 +1048,14 @@ func (parser *PdfParser) parseXrefStream(xstm *PdfObjectInteger) (*PdfObjectDict
common.Log.Trace("- Free object - can probably ignore")
} else if ftype == 1 {
common.Log.Trace("- In use - uncompressed via offset %b", p2)
// If offset (n2) is same as the XRefs table offset, then update the Object number with the
// one that was parsed. Fixes problem where the object number is incorrectly or not specified
// in the Index.
if n2 == xsOffset {
common.Log.Debug("Updating object number for XRef table %d -> %d", objNum, xs.ObjectNumber)
objNum = int(xs.ObjectNumber)
}
// Object type 1: Objects that are in use but are not
// compressed, i.e. defined by an offset (normal entry)
if xr, ok := parser.xrefs[objNum]; !ok || int(n3) > xr.Generation {
@ -1546,6 +1562,8 @@ func NewParserFromString(txt string) *PdfParser {
parser.fileSize = int64(len(txt))
parser.streamLengthReferenceLookupInProgress = map[int64]bool{}
parser.xrefs = XrefTable{}
return &parser
}

BIN
pdf/core/testdata/obj94_xrefs vendored Normal file

Binary file not shown.