Commit e93f7ff527706f5c42eb91c223ccae3df2d8f58e

Authored by m-holger
1 parent 49043112

Tidy QPDF::resolveObjectsInStream

include/qpdf/QPDF.hh
... ... @@ -48,6 +48,7 @@
48 48 class QPDF_Stream;
49 49 class BitStream;
50 50 class BitWriter;
  51 +class BufferInputSource;
51 52 class QPDFLogger;
52 53 class QPDFParser;
53 54  
... ... @@ -784,7 +785,7 @@ class QPDF
784 785 QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og);
785 786 void readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset);
786 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 789 size_t recoverStreamLength(
789 790 std::shared_ptr<InputSource> input, QPDFObjGen og, qpdf_offset_t stream_offset);
790 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 1292 }
1293 1293  
1294 1294 QPDFObjectHandle
1295   -QPDF::readObjectInStream(std::shared_ptr<InputSource>& input, int obj)
  1295 +QPDF::readObjectInStream(BufferInputSource& input, int obj)
1296 1296 {
1297 1297 m->last_object_description.erase(7); // last_object_description starts with "object "
1298 1298 m->last_object_description += std::to_string(obj);
1299 1299 m->last_object_description += " 0";
1300 1300  
1301 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 1303 .parse(empty, false);
1304 1304 if (empty) {
1305 1305 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
1306 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 1309 return object;
1310 1310 }
... ... @@ -1610,7 +1610,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1610 1610 }
1611 1611 m->resolved_object_streams.insert(obj_stream_number);
1612 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 1614 if (!obj_stream.isStream()) {
1615 1615 throw damagedPDF(
1616 1616 "object " + std::to_string(obj_stream_number) + " 0",
... ... @@ -1631,33 +1631,29 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1631 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 1637 throw damagedPDF(
1636 1638 "object " + std::to_string(obj_stream_number) + " 0",
1637 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 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 1652 if (!(tnum.isInteger() && toffset.isInteger())) {
1657 1653 throw damagedPDF(
1658   - *input,
  1654 + input,
1659 1655 "object " + std::to_string(obj_stream_number) + " 0",
1660   - input->getLastOffset(),
  1656 + input.getLastOffset(),
1661 1657 "expected integer in object stream header");
1662 1658 }
1663 1659  
... ... @@ -1667,9 +1663,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1667 1663 if (num == obj_stream_number) {
1668 1664 QTC::TC("qpdf", "QPDF ignore self-referential object stream");
1669 1665 warn(damagedPDF(
1670   - *input,
  1666 + input,
1671 1667 "object " + std::to_string(obj_stream_number) + " 0",
1672   - input->getLastOffset(),
  1668 + input.getLastOffset(),
1673 1669 "object stream claims to contain itself"));
1674 1670 continue;
1675 1671 }
... ... @@ -1677,9 +1673,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1677 1673 if (num < 1) {
1678 1674 QTC::TC("qpdf", "QPDF object stream contains id < 1");
1679 1675 warn(damagedPDF(
1680   - *input,
  1676 + input,
1681 1677 "object " + std::to_string(num) + " 0",
1682   - input->getLastOffset(),
  1678 + input.getLastOffset(),
1683 1679 "object id is invalid"s));
1684 1680 continue;
1685 1681 }
... ... @@ -1687,7 +1683,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1687 1683 if (offset <= last_offset) {
1688 1684 QTC::TC("qpdf", "QPDF object stream offsets not increasing");
1689 1685 warn(damagedPDF(
1690   - *input,
  1686 + input,
1691 1687 "object " + std::to_string(num) + " 0",
1692 1688 offset,
1693 1689 "offset is invalid (must be larger than previous offset " +
... ... @@ -1700,7 +1696,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1700 1696 continue;
1701 1697 }
1702 1698  
1703   - offsets[num] = toI(offset + first);
  1699 + offsets.emplace_back(num, offset + first);
1704 1700 }
1705 1701  
1706 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 1705 // cache what would actually be resolved here.
1710 1706 m->last_object_description.clear();
1711 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 1710 auto entry = m->xref_table.find(og);
1715 1711 if (entry != m->xref_table.end() && entry->second.getType() == 2 &&
1716 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 1715 updateCache(og, oh.getObj(), end_before_space, end_after_space);
1721 1716 } else {
1722 1717 QTC::TC("qpdf", "QPDF not caching overridden objstm object");
... ...