Commit c5d0428da21c9b2531fcf6b83f08a52eb7a86a4a

Authored by m-holger
1 parent 556c34f0

Modify QPDF::getObject to not to resolve the object

libqpdf/QPDF.cc
... ... @@ -26,6 +26,7 @@
26 26 #include <qpdf/QPDF_Null.hh>
27 27 #include <qpdf/QPDF_Reserved.hh>
28 28 #include <qpdf/QPDF_Stream.hh>
  29 +#include <qpdf/QPDF_Unresolved.hh>
29 30 #include <qpdf/QTC.hh>
30 31 #include <qpdf/QUtil.hh>
31 32  
... ... @@ -1397,7 +1398,7 @@ QPDF::fixDanglingReferences(bool force)
1397 1398 std::list<QPDFObjectHandle> queue;
1398 1399 queue.push_back(this->m->trailer);
1399 1400 for (auto const& og: to_process) {
1400   - auto obj = getObjectByObjGen(og);
  1401 + auto obj = getObject(og);
1401 1402 if (obj.isDictionary() || obj.isArray()) {
1402 1403 queue.push_back(obj);
1403 1404 } else if (obj.isStream()) {
... ... @@ -1424,11 +1425,10 @@ QPDF::fixDanglingReferences(bool force)
1424 1425 }
1425 1426 for (auto sub: to_check) {
1426 1427 if (sub.isIndirect()) {
1427   - if (sub.getOwningQPDF() == this) {
1428   - if (!isCached(sub.getObjGen())) {
1429   - QTC::TC("qpdf", "QPDF detected dangling ref");
1430   - queue.push_back(sub);
1431   - }
  1428 + if ((sub.getOwningQPDF() == this) &&
  1429 + isUnresolved(sub.getObjGen())) {
  1430 + QTC::TC("qpdf", "QPDF detected dangling ref");
  1431 + queue.push_back(sub);
1432 1432 }
1433 1433 } else {
1434 1434 queue.push_back(sub);
... ... @@ -1885,7 +1885,7 @@ QPDF::readObjectAtOffset(
1885 1885 "expected endobj");
1886 1886 }
1887 1887  
1888   - if (!isCached(og)) {
  1888 + if (isUnresolved(og)) {
1889 1889 // Store the object in the cache here so it gets cached
1890 1890 // whether we first know the offset or whether we first know
1891 1891 // the object ID and generation (in which we case we would get
... ... @@ -1916,8 +1916,8 @@ QPDF::readObjectAtOffset(
1916 1916 }
1917 1917 }
1918 1918 qpdf_offset_t end_after_space = this->m->file->tell();
1919   -
1920   - this->m->obj_cache[og] = ObjCache(
  1919 + updateCache(
  1920 + og,
1921 1921 QPDFObjectHandle::ObjAccessor::getObject(oh),
1922 1922 end_before_space,
1923 1923 end_after_space);
... ... @@ -1929,6 +1929,11 @@ QPDF::readObjectAtOffset(
1929 1929 std::shared_ptr<QPDFObject>
1930 1930 QPDF::resolve(QPDFObjGen const& og)
1931 1931 {
  1932 + if (isCached(og) && !isUnresolved(og)) {
  1933 + // We only need to resolve unresolved objects
  1934 + return m->obj_cache[og].object;
  1935 + }
  1936 +
1932 1937 // Check object cache before checking xref table. This allows us
1933 1938 // to insert things into the object cache that don't actually
1934 1939 // exist in the file.
... ... @@ -1942,11 +1947,13 @@ QPDF::resolve(QPDFObjGen const&amp; og)
1942 1947 "",
1943 1948 this->m->file->getLastOffset(),
1944 1949 ("loop detected resolving object " + og.unparse(' ')));
1945   - return QPDF_Null::create();
  1950 +
  1951 + updateCache(og, QPDF_Null::create(), -1, -1);
  1952 + return m->obj_cache[og].object;
1946 1953 }
1947 1954 ResolveRecorder rr(this, og);
1948 1955  
1949   - if ((!isCached(og)) && this->m->xref_table.count(og)) {
  1956 + if (m->xref_table.count(og) != 0) {
1950 1957 QPDFXRefEntry const& entry = this->m->xref_table[og];
1951 1958 try {
1952 1959 switch (entry.getType()) {
... ... @@ -1984,12 +1991,11 @@ QPDF::resolve(QPDFObjGen const&amp; og)
1984 1991 ": error reading object: " + e.what()));
1985 1992 }
1986 1993 }
1987   - if (!isCached(og)) {
  1994 +
  1995 + if (isUnresolved(og)) {
1988 1996 // PDF spec says unknown objects resolve to the null object.
1989 1997 QTC::TC("qpdf", "QPDF resolve failure to null");
1990   - QPDFObjectHandle oh = QPDFObjectHandle::newNull();
1991   - this->m->obj_cache[og] =
1992   - ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
  1998 + updateCache(og, QPDF_Null::create(), -1, -1);
1993 1999 }
1994 2000  
1995 2001 std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object);
... ... @@ -2084,15 +2090,15 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
2084 2090 // objects appended to the file, so it is necessary to recheck the
2085 2091 // xref table and only cache what would actually be resolved here.
2086 2092 for (auto const& iter: offsets) {
2087   - int obj = iter.first;
2088   - QPDFObjGen og(obj, 0);
  2093 + QPDFObjGen og(iter.first, 0);
2089 2094 QPDFXRefEntry const& entry = this->m->xref_table[og];
2090 2095 if ((entry.getType() == 2) &&
2091 2096 (entry.getObjStreamNumber() == obj_stream_number)) {
2092 2097 int offset = iter.second;
2093 2098 input->seek(offset, SEEK_SET);
2094 2099 QPDFObjectHandle oh = readObject(input, "", og, true);
2095   - this->m->obj_cache[og] = ObjCache(
  2100 + updateCache(
  2101 + og,
2096 2102 QPDFObjectHandle::ObjAccessor::getObject(oh),
2097 2103 end_before_space,
2098 2104 end_after_space);
... ... @@ -2176,8 +2182,14 @@ QPDF::reserveStream(QPDFObjGen const&amp; og)
2176 2182 QPDFObjectHandle
2177 2183 QPDF::getObject(QPDFObjGen const& og)
2178 2184 {
2179   - auto obj = (og.getObj() != 0) ? resolve(og) : QPDF_Null::create();
2180   - return newIndirect(og, obj);
  2185 + if (!og.isIndirect()) {
  2186 + return QPDFObjectHandle::newNull();
  2187 + }
  2188 + // auto obj = (og.getObj() != 0) ? resolve(og) : QPDF_Null::create();
  2189 + if (!m->obj_cache.count(og)) {
  2190 + m->obj_cache[og] = ObjCache(QPDF_Unresolved::create(), -1, -1);
  2191 + }
  2192 + return newIndirect(og, m->obj_cache[og].object);
2181 2193 }
2182 2194  
2183 2195 QPDFObjectHandle
... ...
qpdf/qtest/qpdf/issue-51.out
... ... @@ -9,7 +9,6 @@ WARNING: issue-51.pdf (object 2 0, offset 26): /Length key in stream dictionary
9 9 WARNING: issue-51.pdf (object 2 0, offset 71): attempting to recover stream length
10 10 WARNING: issue-51.pdf (object 2 0, offset 71): unable to recover stream data; treating stream as empty
11 11 WARNING: issue-51.pdf (object 2 0, offset 977): expected endobj
12   -WARNING: issue-51.pdf (object 2 0, offset 977): EOF after endobj
13 12 WARNING: issue-51.pdf (object 3 0): object has offset 0
14 13 WARNING: issue-51.pdf (object 4 0): object has offset 0
15 14 WARNING: issue-51.pdf (object 5 0): object has offset 0
... ...