mirror of
https://github.com/unidoc/unipdf.git
synced 2025-05-07 19:29:16 +08:00
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:
parent
80014220cd
commit
ea91b30b1b
46
pdf/core/crossrefs_test.go
Normal file
46
pdf/core/crossrefs_test.go
Normal 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)
|
||||
}
|
@ -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
BIN
pdf/core/testdata/obj94_xrefs
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user