Commit ddfa3a24f04606b7c46fc41bd9cfe8c3f0876bc8

Authored by m-holger
Committed by GitHub
2 parents a2389850 5d25aac6

Merge pull request #1281 from m-holger/input

Replace some std::shared_ptr parameters with reference parameters
include/qpdf/QPDF.hh
... ... @@ -1061,7 +1061,7 @@ class QPDF
1061 1061 QPDFObjectHandle readObjectInStream(std::shared_ptr<InputSource>& input, int obj);
1062 1062 size_t recoverStreamLength(
1063 1063 std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset);
1064   - QPDFTokenizer::Token readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
  1064 + QPDFTokenizer::Token readToken(InputSource&, size_t max_len = 0);
1065 1065  
1066 1066 QPDFObjectHandle readObjectAtOffset(
1067 1067 bool attempt_recovery,
... ... @@ -1088,14 +1088,11 @@ class QPDF
1088 1088 qpdf_offset_t end_before_space,
1089 1089 qpdf_offset_t end_after_space);
1090 1090 static QPDFExc damagedPDF(
1091   - std::shared_ptr<InputSource> const& input,
  1091 + InputSource& input,
1092 1092 std::string const& object,
1093 1093 qpdf_offset_t offset,
1094 1094 std::string const& message);
1095   - QPDFExc damagedPDF(
1096   - std::shared_ptr<InputSource> const& input,
1097   - qpdf_offset_t offset,
1098   - std::string const& message);
  1095 + QPDFExc damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message);
1099 1096 QPDFExc damagedPDF(std::string const& object, qpdf_offset_t offset, std::string const& message);
1100 1097 QPDFExc damagedPDF(std::string const& object, std::string const& message);
1101 1098 QPDFExc damagedPDF(qpdf_offset_t offset, std::string const& message);
... ...
libqpdf/QPDF.cc
... ... @@ -419,7 +419,7 @@ QPDF::findHeader()
419 419 bool
420 420 QPDF::findStartxref()
421 421 {
422   - if (readToken(m->file).isWord("startxref") && readToken(m->file).isInteger()) {
  422 + if (readToken(*m->file).isWord("startxref") && readToken(*m->file).isInteger()) {
423 423 // Position in front of offset token
424 424 m->file->seek(m->file->getLastOffset(), SEEK_SET);
425 425 return true;
... ... @@ -457,7 +457,7 @@ QPDF::parse(char const* password)
457 457 PatternFinder sf(*this, &QPDF::findStartxref);
458 458 qpdf_offset_t xref_offset = 0;
459 459 if (m->file->findLast("startxref", start_offset, 0, sf)) {
460   - xref_offset = QUtil::string_to_ll(readToken(m->file).getValue().c_str());
  460 + xref_offset = QUtil::string_to_ll(readToken(*m->file).getValue().c_str());
461 461 }
462 462  
463 463 try {
... ... @@ -575,12 +575,12 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
575 575 // Don't allow very long tokens here during recovery. All the interesting tokens are covered.
576 576 static size_t const MAX_LEN = 10;
577 577 while (m->file->tell() < eof) {
578   - QPDFTokenizer::Token t1 = readToken(m->file, MAX_LEN);
  578 + QPDFTokenizer::Token t1 = readToken(*m->file, MAX_LEN);
579 579 qpdf_offset_t token_start = m->file->tell() - toO(t1.getValue().length());
580 580 if (t1.isInteger()) {
581 581 auto pos = m->file->tell();
582   - QPDFTokenizer::Token t2 = readToken(m->file, MAX_LEN);
583   - if ((t2.isInteger()) && (readToken(m->file, MAX_LEN).isWord("obj"))) {
  582 + QPDFTokenizer::Token t2 = readToken(*m->file, MAX_LEN);
  583 + if ((t2.isInteger()) && (readToken(*m->file, MAX_LEN).isWord("obj"))) {
584 584 int obj = QUtil::string_to_int(t1.getValue().c_str());
585 585 int gen = QUtil::string_to_int(t2.getValue().c_str());
586 586 if (obj <= m->xref_table_max_id) {
... ... @@ -989,7 +989,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
989 989 }
990 990 }
991 991 qpdf_offset_t pos = m->file->tell();
992   - if (readToken(m->file).isWord("trailer")) {
  992 + if (readToken(*m->file).isWord("trailer")) {
993 993 break;
994 994 } else {
995 995 m->file->seek(pos, SEEK_SET);
... ... @@ -1465,12 +1465,12 @@ QPDF::readTrailer()
1465 1465 qpdf_offset_t offset = m->file->tell();
1466 1466 bool empty = false;
1467 1467 auto object =
1468   - QPDFParser(m->file, "trailer", m->tokenizer, nullptr, this, true).parse(empty, false);
  1468 + QPDFParser(*m->file, "trailer", m->tokenizer, nullptr, this, true).parse(empty, false);
1469 1469 if (empty) {
1470 1470 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
1471 1471 // actual PDF files and Adobe Reader appears to ignore them.
1472 1472 warn(damagedPDF("trailer", "empty object treated as null"));
1473   - } else if (object.isDictionary() && readToken(m->file).isWord("stream")) {
  1473 + } else if (object.isDictionary() && readToken(*m->file).isWord("stream")) {
1474 1474 warn(damagedPDF("trailer", m->file->tell(), "stream keyword found in trailer"));
1475 1475 }
1476 1476 // Override last_offset so that it points to the beginning of the object we just read
... ... @@ -1488,18 +1488,18 @@ QPDF::readObject(std::string const&amp; description, QPDFObjGen og)
1488 1488 StringDecrypter decrypter{this, og};
1489 1489 StringDecrypter* decrypter_ptr = m->encp->encrypted ? &decrypter : nullptr;
1490 1490 auto object =
1491   - QPDFParser(m->file, m->last_object_description, m->tokenizer, decrypter_ptr, this, true)
  1491 + QPDFParser(*m->file, m->last_object_description, m->tokenizer, decrypter_ptr, this, true)
1492 1492 .parse(empty, false);
1493 1493 if (empty) {
1494 1494 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
1495 1495 // actual PDF files and Adobe Reader appears to ignore them.
1496   - warn(damagedPDF(m->file, m->file->getLastOffset(), "empty object treated as null"));
  1496 + warn(damagedPDF(*m->file, m->file->getLastOffset(), "empty object treated as null"));
1497 1497 return object;
1498 1498 }
1499   - auto token = readToken(m->file);
  1499 + auto token = readToken(*m->file);
1500 1500 if (object.isDictionary() && token.isWord("stream")) {
1501 1501 readStream(object, og, offset);
1502   - token = readToken(m->file);
  1502 + token = readToken(*m->file);
1503 1503 }
1504 1504 if (!token.isWord("endobj")) {
1505 1505 QTC::TC("qpdf", "QPDF err expected endobj");
... ... @@ -1535,7 +1535,7 @@ QPDF::readStream(QPDFObjectHandle&amp; object, QPDFObjGen og, qpdf_offset_t offset)
1535 1535 // Seek in two steps to avoid potential integer overflow
1536 1536 m->file->seek(stream_offset, SEEK_SET);
1537 1537 m->file->seek(toO(length), SEEK_CUR);
1538   - if (!readToken(m->file).isWord("endstream")) {
  1538 + if (!readToken(*m->file).isWord("endstream")) {
1539 1539 QTC::TC("qpdf", "QPDF missing endstream");
1540 1540 throw damagedPDF("expected endstream");
1541 1541 }
... ... @@ -1608,12 +1608,12 @@ QPDF::readObjectInStream(std::shared_ptr&lt;InputSource&gt;&amp; input, int obj)
1608 1608 m->last_object_description += " 0";
1609 1609  
1610 1610 bool empty = false;
1611   - auto object = QPDFParser(input, m->last_object_description, m->tokenizer, nullptr, this, true)
  1611 + auto object = QPDFParser(*input, m->last_object_description, m->tokenizer, nullptr, this, true)
1612 1612 .parse(empty, false);
1613 1613 if (empty) {
1614 1614 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
1615 1615 // actual PDF files and Adobe Reader appears to ignore them.
1616   - warn(damagedPDF(input, input->getLastOffset(), "empty object treated as null"));
  1616 + warn(damagedPDF(*input, input->getLastOffset(), "empty object treated as null"));
1617 1617 }
1618 1618 return object;
1619 1619 }
... ... @@ -1622,7 +1622,7 @@ bool
1622 1622 QPDF::findEndstream()
1623 1623 {
1624 1624 // Find endstream or endobj. Position the input at that token.
1625   - auto t = readToken(m->file, 20);
  1625 + auto t = readToken(*m->file, 20);
1626 1626 if (t.isWord("endobj") || t.isWord("endstream")) {
1627 1627 m->file->seek(m->file->getLastOffset(), SEEK_SET);
1628 1628 return true;
... ... @@ -1635,14 +1635,14 @@ QPDF::recoverStreamLength(
1635 1635 std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset)
1636 1636 {
1637 1637 // Try to reconstruct stream length by looking for endstream or endobj
1638   - warn(damagedPDF(input, stream_offset, "attempting to recover stream length"));
  1638 + warn(damagedPDF(*input, stream_offset, "attempting to recover stream length"));
1639 1639  
1640 1640 PatternFinder ef(*this, &QPDF::findEndstream);
1641 1641 size_t length = 0;
1642 1642 if (m->file->findFirst("end", stream_offset, 0, ef)) {
1643 1643 length = toS(m->file->tell() - stream_offset);
1644 1644 // Reread endstream but, if it was endobj, don't skip that.
1645   - QPDFTokenizer::Token t = readToken(m->file);
  1645 + QPDFTokenizer::Token t = readToken(*m->file);
1646 1646 if (t.getValue() == "endobj") {
1647 1647 m->file->seek(m->file->getLastOffset(), SEEK_SET);
1648 1648 }
... ... @@ -1674,10 +1674,10 @@ QPDF::recoverStreamLength(
1674 1674  
1675 1675 if (length == 0) {
1676 1676 warn(damagedPDF(
1677   - input, stream_offset, "unable to recover stream data; treating stream as empty"));
  1677 + *input, stream_offset, "unable to recover stream data; treating stream as empty"));
1678 1678 } else {
1679   - warn(
1680   - damagedPDF(input, stream_offset, "recovered stream length: " + std::to_string(length)));
  1679 + warn(damagedPDF(
  1680 + *input, stream_offset, "recovered stream length: " + std::to_string(length)));
1681 1681 }
1682 1682  
1683 1683 QTC::TC("qpdf", "QPDF recovered stream length");
... ... @@ -1685,7 +1685,7 @@ QPDF::recoverStreamLength(
1685 1685 }
1686 1686  
1687 1687 QPDFTokenizer::Token
1688   -QPDF::readToken(std::shared_ptr<InputSource> input, size_t max_len)
  1688 +QPDF::readToken(InputSource& input, size_t max_len)
1689 1689 {
1690 1690 return m->tokenizer.readToken(input, m->last_object_description, true, max_len);
1691 1691 }
... ... @@ -1728,20 +1728,20 @@ QPDF::readObjectAtOffset(
1728 1728  
1729 1729 m->file->seek(offset, SEEK_SET);
1730 1730 try {
1731   - QPDFTokenizer::Token tobjid = readToken(m->file);
  1731 + QPDFTokenizer::Token tobjid = readToken(*m->file);
1732 1732 bool objidok = tobjid.isInteger();
1733 1733 QTC::TC("qpdf", "QPDF check objid", objidok ? 1 : 0);
1734 1734 if (!objidok) {
1735 1735 QTC::TC("qpdf", "QPDF expected n n obj");
1736 1736 throw damagedPDF(offset, "expected n n obj");
1737 1737 }
1738   - QPDFTokenizer::Token tgen = readToken(m->file);
  1738 + QPDFTokenizer::Token tgen = readToken(*m->file);
1739 1739 bool genok = tgen.isInteger();
1740 1740 QTC::TC("qpdf", "QPDF check generation", genok ? 1 : 0);
1741 1741 if (!genok) {
1742 1742 throw damagedPDF(offset, "expected n n obj");
1743 1743 }
1744   - QPDFTokenizer::Token tobj = readToken(m->file);
  1744 + QPDFTokenizer::Token tobj = readToken(*m->file);
1745 1745  
1746 1746 bool objok = tobj.isWord("obj");
1747 1747 QTC::TC("qpdf", "QPDF check obj", objok ? 1 : 0);
... ... @@ -1954,11 +1954,11 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1954 1954 bp.get()));
1955 1955  
1956 1956 for (int i = 0; i < n; ++i) {
1957   - QPDFTokenizer::Token tnum = readToken(input);
1958   - QPDFTokenizer::Token toffset = readToken(input);
  1957 + QPDFTokenizer::Token tnum = readToken(*input);
  1958 + QPDFTokenizer::Token toffset = readToken(*input);
1959 1959 if (!(tnum.isInteger() && toffset.isInteger())) {
1960 1960 throw damagedPDF(
1961   - input,
  1961 + *input,
1962 1962 m->last_object_description,
1963 1963 input->getLastOffset(),
1964 1964 "expected integer in object stream header");
... ... @@ -1972,7 +1972,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1972 1972 if (num == obj_stream_number) {
1973 1973 QTC::TC("qpdf", "QPDF ignore self-referential object stream");
1974 1974 warn(damagedPDF(
1975   - input,
  1975 + *input,
1976 1976 m->last_object_description,
1977 1977 input->getLastOffset(),
1978 1978 "object stream claims to contain itself"));
... ... @@ -2726,7 +2726,7 @@ QPDF::pipeStreamData(
2726 2726 file->seek(offset, SEEK_SET);
2727 2727 auto buf = std::make_unique<char[]>(length);
2728 2728 if (auto read = file->read(buf.get(), length); read != length) {
2729   - throw damagedPDF(file, "", offset + toO(read), "unexpected EOF reading stream data");
  2729 + throw damagedPDF(*file, "", offset + toO(read), "unexpected EOF reading stream data");
2730 2730 }
2731 2731 pipeline->write(buf.get(), length);
2732 2732 attempted_finish = true;
... ... @@ -2742,7 +2742,7 @@ QPDF::pipeStreamData(
2742 2742 qpdf_for_warning.warn(
2743 2743 // line-break
2744 2744 damagedPDF(
2745   - file,
  2745 + *file,
2746 2746 "",
2747 2747 file->getLastOffset(),
2748 2748 ("error decoding stream data for object " + og.unparse(' ') + ": " +
... ... @@ -2751,7 +2751,7 @@ QPDF::pipeStreamData(
2751 2751 qpdf_for_warning.warn(
2752 2752 // line-break
2753 2753 damagedPDF(
2754   - file,
  2754 + *file,
2755 2755 "",
2756 2756 file->getLastOffset(),
2757 2757 "stream will be re-processed without filtering to avoid data loss"));
... ... @@ -2825,19 +2825,15 @@ QPDF::stopOnError(std::string const&amp; message)
2825 2825 // Return an exception of type qpdf_e_damaged_pdf.
2826 2826 QPDFExc
2827 2827 QPDF::damagedPDF(
2828   - std::shared_ptr<InputSource> const& input,
2829   - std::string const& object,
2830   - qpdf_offset_t offset,
2831   - std::string const& message)
  2828 + InputSource& input, std::string const& object, qpdf_offset_t offset, std::string const& message)
2832 2829 {
2833   - return {qpdf_e_damaged_pdf, input->getName(), object, offset, message};
  2830 + return {qpdf_e_damaged_pdf, input.getName(), object, offset, message};
2834 2831 }
2835 2832  
2836 2833 // Return an exception of type qpdf_e_damaged_pdf. The object is taken from
2837 2834 // m->last_object_description.
2838 2835 QPDFExc
2839   -QPDF::damagedPDF(
2840   - std::shared_ptr<InputSource> const& input, qpdf_offset_t offset, std::string const& message)
  2836 +QPDF::damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message)
2841 2837 {
2842 2838 return damagedPDF(input, m->last_object_description, offset, message);
2843 2839 }
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -2164,7 +2164,7 @@ QPDFObjectHandle::parseContentStream_data(
2164 2164 qpdf_offset_t offset = input->getLastOffset();
2165 2165 input->seek(offset, SEEK_SET);
2166 2166 auto obj =
2167   - QPDFParser(input, "content", tokenizer, nullptr, context, false).parse(empty, true);
  2167 + QPDFParser(*input, "content", tokenizer, nullptr, context, false).parse(empty, true);
2168 2168 if (!obj.isInitialized()) {
2169 2169 // EOF
2170 2170 break;
... ... @@ -2223,7 +2223,7 @@ QPDFObjectHandle::parse(
2223 2223 StringDecrypter* decrypter,
2224 2224 QPDF* context)
2225 2225 {
2226   - return QPDFParser(input, object_description, tokenizer, decrypter, context, false)
  2226 + return QPDFParser(*input, object_description, tokenizer, decrypter, context, false)
2227 2227 .parse(empty, false);
2228 2228 }
2229 2229  
... ...
libqpdf/QPDFParser.cc
... ... @@ -33,9 +33,9 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
33 33  
34 34 QPDF::ParseGuard pg(context);
35 35 empty = false;
36   - start = input->tell();
  36 + start = input.tell();
37 37  
38   - if (!tokenizer.nextToken(*input, object_description)) {
  38 + if (!tokenizer.nextToken(input, object_description)) {
39 39 warn(tokenizer.getErrorMessage());
40 40 }
41 41  
... ... @@ -101,7 +101,7 @@ QPDFParser::parse(bool&amp; empty, bool content_stream)
101 101 } else if (value == "endobj") {
102 102 // We just saw endobj without having read anything. Treat this as a null and do
103 103 // not move the input source's offset.
104   - input->seek(input->getLastOffset(), SEEK_SET);
  104 + input.seek(input.getLastOffset(), SEEK_SET);
105 105 empty = true;
106 106 return {QPDF_Null::create()};
107 107 } else {
... ... @@ -138,7 +138,7 @@ QPDFParser::parseRemainder(bool content_stream)
138 138 bool b_contents = false;
139 139  
140 140 while (true) {
141   - if (!tokenizer.nextToken(*input, object_description)) {
  141 + if (!tokenizer.nextToken(input, object_description)) {
142 142 warn(tokenizer.getErrorMessage());
143 143 }
144 144 ++good_count; // optimistically
... ... @@ -151,7 +151,7 @@ QPDFParser::parseRemainder(bool content_stream)
151 151 // Process the oldest buffered integer.
152 152 addInt(int_count);
153 153 }
154   - last_offset_buffer[int_count % 2] = input->getLastOffset();
  154 + last_offset_buffer[int_count % 2] = input.getLastOffset();
155 155 int_buffer[int_count % 2] = QUtil::string_to_ll(tokenizer.getValue().c_str());
156 156 continue;
157 157  
... ... @@ -309,7 +309,7 @@ QPDFParser::parseRemainder(bool content_stream)
309 309 case QPDFTokenizer::tt_integer:
310 310 if (!content_stream) {
311 311 // Buffer token in case it is part of an indirect reference.
312   - last_offset_buffer[1] = input->getLastOffset();
  312 + last_offset_buffer[1] = input.getLastOffset();
313 313 int_buffer[1] = QUtil::string_to_ll(tokenizer.getValue().c_str());
314 314 int_count = 1;
315 315 } else {
... ... @@ -351,7 +351,7 @@ QPDFParser::parseRemainder(bool content_stream)
351 351 if (decrypter) {
352 352 if (b_contents) {
353 353 frame->contents_string = val;
354   - frame->contents_offset = input->getLastOffset();
  354 + frame->contents_offset = input.getLastOffset();
355 355 b_contents = false;
356 356 }
357 357 std::string s{val};
... ... @@ -419,7 +419,7 @@ void
419 419 QPDFParser::addScalar(Args&&... args)
420 420 {
421 421 auto obj = T::create(args...);
422   - obj->setDescription(context, description, input->getLastOffset());
  422 + obj->setDescription(context, description, input.getLastOffset());
423 423 add(std::move(obj));
424 424 }
425 425  
... ... @@ -506,11 +506,11 @@ QPDFParser::warnDuplicateKey()
506 506 void
507 507 QPDFParser::warn(qpdf_offset_t offset, std::string const& msg) const
508 508 {
509   - warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(), object_description, offset, msg));
  509 + warn(QPDFExc(qpdf_e_damaged_pdf, input.getName(), object_description, offset, msg));
510 510 }
511 511  
512 512 void
513 513 QPDFParser::warn(std::string const& msg) const
514 514 {
515   - warn(input->getLastOffset(), msg);
  515 + warn(input.getLastOffset(), msg);
516 516 }
... ...
libqpdf/QPDF_linearization.cc
... ... @@ -118,9 +118,10 @@ QPDF::isLinearized()
118 118 ++p;
119 119 }
120 120  
121   - QPDFTokenizer::Token t1 = readToken(m->file);
122   - if (t1.isInteger() && readToken(m->file).isInteger() && readToken(m->file).isWord("obj") &&
123   - (readToken(m->file).getType() == QPDFTokenizer::tt_dict_open)) {
  121 + QPDFTokenizer::Token t1 = readToken(*m->file);
  122 + if (t1.isInteger() && readToken(*m->file).isInteger() &&
  123 + readToken(*m->file).isWord("obj") &&
  124 + readToken(*m->file).getType() == QPDFTokenizer::tt_dict_open) {
124 125 lindict_obj = toI(QUtil::string_to_ll(t1.getValue().c_str()));
125 126 }
126 127 }
... ...
libqpdf/qpdf/QPDFParser.hh
... ... @@ -12,7 +12,7 @@ class QPDFParser
12 12 public:
13 13 QPDFParser() = delete;
14 14 QPDFParser(
15   - std::shared_ptr<InputSource> input,
  15 + InputSource& input,
16 16 std::string const& object_description,
17 17 QPDFTokenizer& tokenizer,
18 18 QPDFObjectHandle::StringDecrypter* decrypter,
... ... @@ -24,7 +24,7 @@ class QPDFParser
24 24 decrypter(decrypter),
25 25 context(context),
26 26 description(std::make_shared<QPDFValue::Description>(
27   - std::string(input->getName() + ", " + object_description + " at offset $PO"))),
  27 + std::string(input.getName() + ", " + object_description + " at offset $PO"))),
28 28 parse_pdf(parse_pdf)
29 29 {
30 30 }
... ... @@ -39,9 +39,9 @@ class QPDFParser
39 39  
40 40 struct StackFrame
41 41 {
42   - StackFrame(std::shared_ptr<InputSource> const& input, parser_state_e state) :
  42 + StackFrame(InputSource& input, parser_state_e state) :
43 43 state(state),
44   - offset(input->tell())
  44 + offset(input.tell())
45 45 {
46 46 }
47 47  
... ... @@ -72,7 +72,7 @@ class QPDFParser
72 72 // NB the offset includes any leading whitespace.
73 73 QPDFObjectHandle withDescription(Args&&... args);
74 74 void setDescription(std::shared_ptr<QPDFObject>& obj, qpdf_offset_t parsed_offset);
75   - std::shared_ptr<InputSource> input;
  75 + InputSource& input;
76 76 std::string const& object_description;
77 77 QPDFTokenizer& tokenizer;
78 78 QPDFObjectHandle::StringDecrypter* decrypter;
... ...