Commit e063f3237dff54e547ba78e3d34eb9a77f3e2a00

Authored by m-holger
Committed by GitHub
2 parents 52e63412 f06209ca

Merge pull request #1384 from m-holger/ostream

Enhance error checking of object stream object ids and offsets
include/qpdf/QPDFXRefEntry.hh
... ... @@ -62,6 +62,9 @@ class QPDFXRefEntry
62 62 private:
63 63 // This class does not use the Members pattern to avoid a memory allocation for every one of
64 64 // these. A lot of these get created.
  65 +
  66 + // The layout can be changed to reduce the size from 24 to 16 bytes. However, this would have a
  67 + // definite runtime cost.
65 68 int type{0};
66 69 qpdf_offset_t field1{0};
67 70 int field2{0};
... ...
libqpdf/QPDF.cc
... ... @@ -25,6 +25,7 @@
25 25 #include <qpdf/Util.hh>
26 26  
27 27 using namespace qpdf;
  28 +using namespace std::literals;
28 29  
29 30 // This must be a fixed value. This API returns a const reference to it, and the C API relies on its
30 31 // being static as well.
... ... @@ -1967,6 +1968,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1967 1968 (m->file->getName() + " object stream " + std::to_string(obj_stream_number)),
1968 1969 bp.get()));
1969 1970  
  1971 + long long last_offset = -1;
1970 1972 for (int i = 0; i < n; ++i) {
1971 1973 QPDFTokenizer::Token tnum = readToken(*input);
1972 1974 QPDFTokenizer::Token toffset = readToken(*input);
... ... @@ -1980,9 +1982,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1980 1982  
1981 1983 int num = QUtil::string_to_int(tnum.getValue().c_str());
1982 1984 long long offset = QUtil::string_to_int(toffset.getValue().c_str());
1983   - if (num > m->xref_table_max_id) {
1984   - continue;
1985   - }
  1985 +
1986 1986 if (num == obj_stream_number) {
1987 1987 QTC::TC("qpdf", "QPDF ignore self-referential object stream");
1988 1988 warn(damagedPDF(
... ... @@ -1992,6 +1992,33 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1992 1992 "object stream claims to contain itself"));
1993 1993 continue;
1994 1994 }
  1995 +
  1996 + if (num < 1) {
  1997 + QTC::TC("qpdf", "QPDF object stream contains id < 1");
  1998 + warn(damagedPDF(
  1999 + *input,
  2000 + "object "s + std::to_string(num) + " 0, offset " + std::to_string(offset),
  2001 + 0,
  2002 + "object id is invalid"s));
  2003 + continue;
  2004 + }
  2005 +
  2006 + if (offset <= last_offset) {
  2007 + QTC::TC("qpdf", "QPDF object stream offsets not increasing");
  2008 + warn(damagedPDF(
  2009 + *input,
  2010 + "object "s + std::to_string(num) + " 0, offset " + std::to_string(offset),
  2011 + 0,
  2012 + "offset is invalid (must be larger than previous offset " +
  2013 + std::to_string(last_offset) + ")"));
  2014 + continue;
  2015 + }
  2016 + last_offset = offset;
  2017 +
  2018 + if (num > m->xref_table_max_id) {
  2019 + continue;
  2020 + }
  2021 +
1995 2022 offsets[num] = toI(offset + first);
1996 2023 }
1997 2024  
... ...
manual/release-notes.rst
... ... @@ -81,6 +81,12 @@ more detail.
81 81 copies the file ``check`` to ``out.pdf`` but may in future check ``out.pdf``.
82 82 Use ``qpdf ./check out.pdf`` or ``qpdf -- check out.pdf`` instead.
83 83  
  84 +
  85 + - Bug fixes
  86 +
  87 + - In object streams ignore objects with invalid offset. Report objects with invalid
  88 + id or offset.
  89 +
84 90 - Library Enhancements
85 91  
86 92 - ``QPDFObjectHandle`` supports move construction/assignment.
... ...
qpdf/qpdf.testcov
... ... @@ -4,7 +4,9 @@ QPDF err wrong objid/generation 0
4 4 QPDF check objid 1
5 5 QPDF check generation 1
6 6 QPDF check obj 1
  7 +QPDF object stream offsets not increasing 0
7 8 QPDF ignore self-referential object stream 0
  9 +QPDF object stream contains id < 1 0
8 10 QPDF hint table length indirect 0
9 11 QPDF hint table length direct 0
10 12 QPDF P absent in lindict 0
... ...
qpdf/qtest/qpdf/issue-143.out
... ... @@ -14,5 +14,9 @@ WARNING: issue-143.pdf (object 1 0, offset 24): expected dictionary key but foun
14 14 WARNING: issue-143.pdf (object 1 0, offset 21): stream dictionary lacks /Length key
15 15 WARNING: issue-143.pdf (object 1 0, offset 84): attempting to recover stream length
16 16 WARNING: issue-143.pdf (object 1 0, offset 84): recovered stream length: 606
  17 +WARNING: issue-143.pdf object stream 1 (object 0 0, offset 0): object id is invalid
  18 +WARNING: issue-143.pdf object stream 1 (object 0 0, offset 0): object id is invalid
  19 +WARNING: issue-143.pdf object stream 1 (object 6 0, offset 0): offset is invalid (must be larger than previous offset 0)
  20 +WARNING: issue-143.pdf object stream 1 (object 0 0, offset 0): object id is invalid
17 21 WARNING: issue-143.pdf object stream 1 (object 2 0, offset 33): expected dictionary key but found non-name object; inserting key /QPDFFake1
18 22 qpdf: issue-143.pdf: unable to find page tree
... ...
qpdf/qtest/qpdf/issue-143.pdf
No preview for this file type