Commit b356b9dfa2fd1b1d15cbd09720d6d8185fa613e5
1 parent
cf43882e
fix-qdf: handle object streams with > 255 objects
fix-qdf was previously hard-coding the number of bytes for the f2 field of the xref stream entry. This addresses issue #37. Thanks aluebcke for reporting.
Showing
4 changed files
with
2249 additions
and
11 deletions
ChangeLog
| 1 | 2015-05-24 Jay Berkenbilt <ejb@ql.org> | 1 | 2015-05-24 Jay Berkenbilt <ejb@ql.org> |
| 2 | 2 | ||
| 3 | + * Bug fix: fix-qdf was not handling object streams with more than | ||
| 4 | + 255 objects in them. | ||
| 5 | + | ||
| 3 | * Handle Microsoft crypt provider initialization properly for case | 6 | * Handle Microsoft crypt provider initialization properly for case |
| 4 | where no keys have been previously created, such as in a fresh | 7 | where no keys have been previously created, such as in a fresh |
| 5 | Windows installation. | 8 | Windows installation. |
qpdf/fix-qdf
| @@ -53,6 +53,7 @@ my $stream_start = 0; | @@ -53,6 +53,7 @@ my $stream_start = 0; | ||
| 53 | my $stream_length = 0; | 53 | my $stream_length = 0; |
| 54 | my $xref_offset = 0; | 54 | my $xref_offset = 0; |
| 55 | my $xref_f1_nbytes = 0; | 55 | my $xref_f1_nbytes = 0; |
| 56 | +my $xref_f2_nbytes = 0; | ||
| 56 | my $xref_size = 0; | 57 | my $xref_size = 0; |
| 57 | 58 | ||
| 58 | my $cur_state = 0; | 59 | my $cur_state = 0; |
| @@ -122,11 +123,28 @@ while (defined($line = get_line())) | @@ -122,11 +123,28 @@ while (defined($line = get_line())) | ||
| 122 | $t >>= 8; | 123 | $t >>= 8; |
| 123 | ++$xref_f1_nbytes; | 124 | ++$xref_f1_nbytes; |
| 124 | } | 125 | } |
| 125 | - my $esize = $xref_f1_nbytes + 2; | 126 | + # Figure out how many bytes we need for ostream index. |
| 127 | + # Make sure we get at least 1 byte even if there are no | ||
| 128 | + # object streams. | ||
| 129 | + my $max_objects = 1; | ||
| 130 | + foreach my $e (@xref) | ||
| 131 | + { | ||
| 132 | + my ($type, $f1, $f2) = @$e; | ||
| 133 | + if ((defined $f2) && ($f2 > $max_objects)) | ||
| 134 | + { | ||
| 135 | + $max_objects = $f2; | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | + while ($max_objects) | ||
| 139 | + { | ||
| 140 | + $max_objects >>=8; | ||
| 141 | + ++$xref_f2_nbytes; | ||
| 142 | + } | ||
| 143 | + my $esize = 1 + $xref_f1_nbytes + $xref_f2_nbytes; | ||
| 126 | $xref_size = 1 + @xref; | 144 | $xref_size = 1 + @xref; |
| 127 | my $length = $xref_size * $esize; | 145 | my $length = $xref_size * $esize; |
| 128 | print " /Length $length\n"; | 146 | print " /Length $length\n"; |
| 129 | - print " /W [ 1 $xref_f1_nbytes 1 ]\n"; | 147 | + print " /W [ 1 $xref_f1_nbytes $xref_f2_nbytes ]\n"; |
| 130 | $state = $st_in_xref_stream_dict; | 148 | $state = $st_in_xref_stream_dict; |
| 131 | } | 149 | } |
| 132 | } | 150 | } |
| @@ -200,19 +218,25 @@ while (defined($line = get_line())) | @@ -200,19 +218,25 @@ while (defined($line = get_line())) | ||
| 200 | } | 218 | } |
| 201 | if ($line =~ m/^stream\n/) | 219 | if ($line =~ m/^stream\n/) |
| 202 | { | 220 | { |
| 203 | - my $pack = "(C C$xref_f1_nbytes C)"; | 221 | + my $pack = "(C C$xref_f1_nbytes C$xref_f2_nbytes)"; |
| 204 | print pack($pack, 0, 0, 0); | 222 | print pack($pack, 0, 0, 0); |
| 205 | foreach my $x (@xref) | 223 | foreach my $x (@xref) |
| 206 | { | 224 | { |
| 207 | my ($type, $f1, $f2) = @$x; | 225 | my ($type, $f1, $f2) = @$x; |
| 208 | $f2 = 0 unless defined $f2; | 226 | $f2 = 0 unless defined $f2; |
| 209 | - my @f1 = (); | ||
| 210 | - for (my $i = 0; $i < $xref_f1_nbytes; ++$i) | ||
| 211 | - { | ||
| 212 | - unshift(@f1, $f1 & 0xff); | ||
| 213 | - $f1 >>= 8; | ||
| 214 | - } | ||
| 215 | - print pack($pack, $type, @f1, $f2); | 227 | + my @f1 = (); |
| 228 | + my @f2 = (); | ||
| 229 | + foreach my $d ([\@f1, $f1, $xref_f1_nbytes], | ||
| 230 | + [\@f2, $f2, $xref_f2_nbytes]) | ||
| 231 | + { | ||
| 232 | + my ($fa, $f, $nbytes) = @$d; | ||
| 233 | + for (my $i = 0; $i < $nbytes; ++$i) | ||
| 234 | + { | ||
| 235 | + unshift(@$fa, $f & 0xff); | ||
| 236 | + $f >>= 8; | ||
| 237 | + } | ||
| 238 | + } | ||
| 239 | + print pack($pack, $type, @f1, @f2); | ||
| 216 | } | 240 | } |
| 217 | print "\nendstream\nendobj\n\n"; | 241 | print "\nendstream\nendobj\n\n"; |
| 218 | print "startxref\n$xref_offset\n\%\%EOF\n"; | 242 | print "startxref\n$xref_offset\n\%\%EOF\n"; |
qpdf/qtest/qpdf.test
| @@ -1993,7 +1993,7 @@ compare_pdfs("inline-images-cr.pdf", "a.pdf"); | @@ -1993,7 +1993,7 @@ compare_pdfs("inline-images-cr.pdf", "a.pdf"); | ||
| 1993 | show_ntests(); | 1993 | show_ntests(); |
| 1994 | # ---------- | 1994 | # ---------- |
| 1995 | $td->notify("--- fix-qdf Tests ---"); | 1995 | $td->notify("--- fix-qdf Tests ---"); |
| 1996 | -$n_tests += 4; | 1996 | +$n_tests += 5; |
| 1997 | 1997 | ||
| 1998 | for (my $n = 1; $n <= 2; ++$n) | 1998 | for (my $n = 1; $n <= 2; ++$n) |
| 1999 | { | 1999 | { |
| @@ -2007,6 +2007,10 @@ for (my $n = 1; $n <= 2; ++$n) | @@ -2007,6 +2007,10 @@ for (my $n = 1; $n <= 2; ++$n) | ||
| 2007 | {$td->FILE => "fix$n.qdf.out", | 2007 | {$td->FILE => "fix$n.qdf.out", |
| 2008 | $td->EXIT_STATUS => 0}); | 2008 | $td->EXIT_STATUS => 0}); |
| 2009 | } | 2009 | } |
| 2010 | +$td->runtest("fix-qdf with big object stream", # > 255 objects in a stream | ||
| 2011 | + {$td->COMMAND => "fix-qdf big-ostream.pdf"}, | ||
| 2012 | + {$td->FILE => "big-ostream.pdf", | ||
| 2013 | + $td->EXIT_STATUS => 0}); | ||
| 2010 | 2014 | ||
| 2011 | show_ntests(); | 2015 | show_ntests(); |
| 2012 | # ---------- | 2016 | # ---------- |
qpdf/qtest/qpdf/big-ostream.pdf
0 → 100644
No preview for this file type