Commit e93f7ff527706f5c42eb91c223ccae3df2d8f58e
1 parent
49043112
Tidy QPDF::resolveObjectsInStream
Showing
2 changed files
with
28 additions
and
32 deletions
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& 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"); | ... | ... |