From c2f5e73cd5f9e322066118d3b91396c6d6fc202c Mon Sep 17 00:00:00 2001 From: Jim Biard Date: Sat, 18 Aug 2018 20:33:06 -0400 Subject: [PATCH 1/2] Updated pdfreader to properly handle xref streams. --- pdfrw/pdfreader.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/pdfrw/pdfreader.py b/pdfrw/pdfreader.py index c2ae030..82ba411 100644 --- a/pdfrw/pdfreader.py +++ b/pdfrw/pdfreader.py @@ -613,18 +613,42 @@ def __init__(self, fname=None, fdata=None, decompress=False, # Find all the xref tables/streams, and # then deal with them backwards. + # xref_list = [] + while 1: source.obj_offsets = {} + trailer, is_stream = self.parsexref(source) - prev = trailer.Prev + + xref_list.append((source.obj_offsets, trailer, is_stream)) + + prev = trailer.Prev + xrefStream = trailer.XRefStm + + # Process any xref stream specified in the trailer, then get + # back to processing any previous xref section specified in the + # trailer. + # + if xrefStream: + source.obj_offsets = {} + + savedLoc = source.floc + + source.floc = int(xrefStream) + + trailer, is_stream = self.parsexref(source) + + xref_list.append((source.obj_offsets, trailer, is_stream)) + + source.floc = savedLoc if prev is None: token = source.next() if token != 'startxref' and not xref_list: source.warning('Expected "startxref" ' 'at end of xref table') break - xref_list.append((source.obj_offsets, trailer, is_stream)) + source.floc = int(prev) # Handle document encryption From 16812d02ddf50318f7d79bda51209e848934daa3 Mon Sep 17 00:00:00 2001 From: Jim Biard Date: Wed, 12 Sep 2018 17:13:01 -0400 Subject: [PATCH 2/2] Fixed a bug I introduced in the order of processing of xref sections. --- pdfrw/pdfreader.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/pdfrw/pdfreader.py b/pdfrw/pdfreader.py index 82ba411..4b179dc 100644 --- a/pdfrw/pdfreader.py +++ b/pdfrw/pdfreader.py @@ -617,31 +617,41 @@ def __init__(self, fname=None, fdata=None, decompress=False, xref_list = [] while 1: + # Parse the xref table, getting object offsets, a trailer, and + # a stream flag. + # source.obj_offsets = {} trailer, is_stream = self.parsexref(source) - xref_list.append((source.obj_offsets, trailer, is_stream)) - + # Get any previous section or xref stream section offsets from + # the trailer. + # prev = trailer.Prev xrefStream = trailer.XRefStm - # Process any xref stream specified in the trailer, then get - # back to processing any previous xref section specified in the - # trailer. + # If there is an xref stream section, process it. # if xrefStream: - source.obj_offsets = {} + # Save off the object offsets, trailer, and stream flag just parsed. + # + xref_list.append((source.obj_offsets, trailer, is_stream)) + # Parse the xref stream section as above, then return the + # source pointer to its original location. + # savedLoc = source.floc + source.obj_offsets = {} + source.floc = int(xrefStream) trailer, is_stream = self.parsexref(source) - xref_list.append((source.obj_offsets, trailer, is_stream)) - source.floc = savedLoc + + # If there is no previous section, finish up and break out of + # the loop. if prev is None: token = source.next() if token != 'startxref' and not xref_list: @@ -649,6 +659,12 @@ def __init__(self, fname=None, fdata=None, decompress=False, 'at end of xref table') break + # There is a previous section, so save off the object offsets, + # trailer, and stream flag just parsed, set the source pointer + # to the previous section, and keep parsing. + # + xref_list.append((source.obj_offsets, trailer, is_stream)) + source.floc = int(prev) # Handle document encryption