Commit e93f7ff527706f5c42eb91c223ccae3df2d8f58e

Authored by m-holger
1 parent 49043112

Tidy QPDF::resolveObjectsInStream

include/qpdf/QPDF.hh
@@ -48,6 +48,7 @@ @@ -48,6 +48,7 @@
48 class QPDF_Stream; 48 class QPDF_Stream;
49 class BitStream; 49 class BitStream;
50 class BitWriter; 50 class BitWriter;
  51 +class BufferInputSource;
51 class QPDFLogger; 52 class QPDFLogger;
52 class QPDFParser; 53 class QPDFParser;
53 54
@@ -784,7 +785,7 @@ class QPDF @@ -784,7 +785,7 @@ class QPDF
784 QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og); 785 QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og);
785 void readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset); 786 void readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset);
786 void validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset); 787 void validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset);
787 - QPDFObjectHandle readObjectInStream(std::shared_ptr<InputSource>& input, int obj); 788 + QPDFObjectHandle readObjectInStream(BufferInputSource& input, int obj);
788 size_t recoverStreamLength( 789 size_t recoverStreamLength(
789 std::shared_ptr<InputSource> input, QPDFObjGen og, qpdf_offset_t stream_offset); 790 std::shared_ptr<InputSource> input, QPDFObjGen og, qpdf_offset_t stream_offset);
790 QPDFTokenizer::Token readToken(InputSource&, size_t max_len = 0); 791 QPDFTokenizer::Token readToken(InputSource&, size_t max_len = 0);
libqpdf/QPDF_objects.cc
@@ -1292,19 +1292,19 @@ QPDF::validateStreamLineEnd(QPDFObjectHandle&amp; object, QPDFObjGen og, qpdf_offset @@ -1292,19 +1292,19 @@ QPDF::validateStreamLineEnd(QPDFObjectHandle&amp; object, QPDFObjGen og, qpdf_offset
1292 } 1292 }
1293 1293
1294 QPDFObjectHandle 1294 QPDFObjectHandle
1295 -QPDF::readObjectInStream(std::shared_ptr<InputSource>& input, int obj) 1295 +QPDF::readObjectInStream(BufferInputSource& input, int obj)
1296 { 1296 {
1297 m->last_object_description.erase(7); // last_object_description starts with "object " 1297 m->last_object_description.erase(7); // last_object_description starts with "object "
1298 m->last_object_description += std::to_string(obj); 1298 m->last_object_description += std::to_string(obj);
1299 m->last_object_description += " 0"; 1299 m->last_object_description += " 0";
1300 1300
1301 bool empty = false; 1301 bool empty = false;
1302 - auto object = QPDFParser(*input, m->last_object_description, m->tokenizer, nullptr, this, true) 1302 + auto object = QPDFParser(input, m->last_object_description, m->tokenizer, nullptr, this, true)
1303 .parse(empty, false); 1303 .parse(empty, false);
1304 if (empty) { 1304 if (empty) {
1305 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in 1305 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
1306 // actual PDF files and Adobe Reader appears to ignore them. 1306 // actual PDF files and Adobe Reader appears to ignore them.
1307 - warn(damagedPDF(*input, input->getLastOffset(), "empty object treated as null")); 1307 + warn(damagedPDF(input, input.getLastOffset(), "empty object treated as null"));
1308 } 1308 }
1309 return object; 1309 return object;
1310 } 1310 }
@@ -1610,7 +1610,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1610,7 +1610,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1610 } 1610 }
1611 m->resolved_object_streams.insert(obj_stream_number); 1611 m->resolved_object_streams.insert(obj_stream_number);
1612 // Force resolution of object stream 1612 // Force resolution of object stream
1613 - QPDFObjectHandle obj_stream = getObjectByID(obj_stream_number, 0); 1613 + QPDFObjectHandle obj_stream = getObject(obj_stream_number, 0);
1614 if (!obj_stream.isStream()) { 1614 if (!obj_stream.isStream()) {
1615 throw damagedPDF( 1615 throw damagedPDF(
1616 "object " + std::to_string(obj_stream_number) + " 0", 1616 "object " + std::to_string(obj_stream_number) + " 0",
@@ -1631,33 +1631,29 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1631,33 +1631,29 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1631 "supposed object stream " + std::to_string(obj_stream_number) + " has wrong type")); 1631 "supposed object stream " + std::to_string(obj_stream_number) + " has wrong type"));
1632 } 1632 }
1633 1633
1634 - if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) { 1634 + unsigned int n{0};
  1635 + int first{0};
  1636 + if (!(dict.getKey("/N").getValueAsUInt(n) && dict.getKey("/First").getValueAsInt(first))) {
1635 throw damagedPDF( 1637 throw damagedPDF(
1636 "object " + std::to_string(obj_stream_number) + " 0", 1638 "object " + std::to_string(obj_stream_number) + " 0",
1637 "object stream " + std::to_string(obj_stream_number) + " has incorrect keys"); 1639 "object stream " + std::to_string(obj_stream_number) + " has incorrect keys");
1638 } 1640 }
1639 1641
1640 - int n = dict.getKey("/N").getIntValueAsInt();  
1641 - int first = dict.getKey("/First").getIntValueAsInt(); 1642 + std::vector<std::pair<int, long long>> offsets;
1642 1643
1643 - std::map<int, int> offsets;  
1644 -  
1645 - std::shared_ptr<Buffer> bp = obj_stream.getStreamData(qpdf_dl_specialized);  
1646 - auto input = std::shared_ptr<InputSource>(  
1647 - // line-break  
1648 - new BufferInputSource(  
1649 - (m->file->getName() + " object stream " + std::to_string(obj_stream_number)),  
1650 - bp.get())); 1644 + auto bp = obj_stream.getStreamData(qpdf_dl_specialized);
  1645 + BufferInputSource input(
  1646 + (m->file->getName() + " object stream " + std::to_string(obj_stream_number)), bp.get());
1651 1647
1652 long long last_offset = -1; 1648 long long last_offset = -1;
1653 - for (int i = 0; i < n; ++i) {  
1654 - QPDFTokenizer::Token tnum = readToken(*input);  
1655 - QPDFTokenizer::Token toffset = readToken(*input); 1649 + for (unsigned int i = 0; i < n; ++i) {
  1650 + auto tnum = readToken(input);
  1651 + auto toffset = readToken(input);
1656 if (!(tnum.isInteger() && toffset.isInteger())) { 1652 if (!(tnum.isInteger() && toffset.isInteger())) {
1657 throw damagedPDF( 1653 throw damagedPDF(
1658 - *input, 1654 + input,
1659 "object " + std::to_string(obj_stream_number) + " 0", 1655 "object " + std::to_string(obj_stream_number) + " 0",
1660 - input->getLastOffset(), 1656 + input.getLastOffset(),
1661 "expected integer in object stream header"); 1657 "expected integer in object stream header");
1662 } 1658 }
1663 1659
@@ -1667,9 +1663,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1667,9 +1663,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1667 if (num == obj_stream_number) { 1663 if (num == obj_stream_number) {
1668 QTC::TC("qpdf", "QPDF ignore self-referential object stream"); 1664 QTC::TC("qpdf", "QPDF ignore self-referential object stream");
1669 warn(damagedPDF( 1665 warn(damagedPDF(
1670 - *input, 1666 + input,
1671 "object " + std::to_string(obj_stream_number) + " 0", 1667 "object " + std::to_string(obj_stream_number) + " 0",
1672 - input->getLastOffset(), 1668 + input.getLastOffset(),
1673 "object stream claims to contain itself")); 1669 "object stream claims to contain itself"));
1674 continue; 1670 continue;
1675 } 1671 }
@@ -1677,9 +1673,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1677,9 +1673,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1677 if (num < 1) { 1673 if (num < 1) {
1678 QTC::TC("qpdf", "QPDF object stream contains id < 1"); 1674 QTC::TC("qpdf", "QPDF object stream contains id < 1");
1679 warn(damagedPDF( 1675 warn(damagedPDF(
1680 - *input, 1676 + input,
1681 "object " + std::to_string(num) + " 0", 1677 "object " + std::to_string(num) + " 0",
1682 - input->getLastOffset(), 1678 + input.getLastOffset(),
1683 "object id is invalid"s)); 1679 "object id is invalid"s));
1684 continue; 1680 continue;
1685 } 1681 }
@@ -1687,7 +1683,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1687,7 +1683,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1687 if (offset <= last_offset) { 1683 if (offset <= last_offset) {
1688 QTC::TC("qpdf", "QPDF object stream offsets not increasing"); 1684 QTC::TC("qpdf", "QPDF object stream offsets not increasing");
1689 warn(damagedPDF( 1685 warn(damagedPDF(
1690 - *input, 1686 + input,
1691 "object " + std::to_string(num) + " 0", 1687 "object " + std::to_string(num) + " 0",
1692 offset, 1688 offset,
1693 "offset is invalid (must be larger than previous offset " + 1689 "offset is invalid (must be larger than previous offset " +
@@ -1700,7 +1696,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1700,7 +1696,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1700 continue; 1696 continue;
1701 } 1697 }
1702 1698
1703 - offsets[num] = toI(offset + first); 1699 + offsets.emplace_back(num, offset + first);
1704 } 1700 }
1705 1701
1706 // To avoid having to read the object stream multiple times, store all objects that would be 1702 // To avoid having to read the object stream multiple times, store all objects that would be
@@ -1709,14 +1705,13 @@ QPDF::resolveObjectsInStream(int obj_stream_number) @@ -1709,14 +1705,13 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1709 // cache what would actually be resolved here. 1705 // cache what would actually be resolved here.
1710 m->last_object_description.clear(); 1706 m->last_object_description.clear();
1711 m->last_object_description += "object "; 1707 m->last_object_description += "object ";
1712 - for (auto const& iter: offsets) {  
1713 - QPDFObjGen og(iter.first, 0); 1708 + for (auto const& [id, offset]: offsets) {
  1709 + QPDFObjGen og(id, 0);
1714 auto entry = m->xref_table.find(og); 1710 auto entry = m->xref_table.find(og);
1715 if (entry != m->xref_table.end() && entry->second.getType() == 2 && 1711 if (entry != m->xref_table.end() && entry->second.getType() == 2 &&
1716 entry->second.getObjStreamNumber() == obj_stream_number) { 1712 entry->second.getObjStreamNumber() == obj_stream_number) {
1717 - int offset = iter.second;  
1718 - input->seek(offset, SEEK_SET);  
1719 - QPDFObjectHandle oh = readObjectInStream(input, iter.first); 1713 + input.seek(offset, SEEK_SET);
  1714 + QPDFObjectHandle oh = readObjectInStream(input, id);
1720 updateCache(og, oh.getObj(), end_before_space, end_after_space); 1715 updateCache(og, oh.getObj(), end_before_space, end_after_space);
1721 } else { 1716 } else {
1722 QTC::TC("qpdf", "QPDF not caching overridden objstm object"); 1717 QTC::TC("qpdf", "QPDF not caching overridden objstm object");