2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-02 22:50:20 +00:00

Merge pull request #1281 from m-holger/input

Replace some std::shared_ptr parameters with reference parameters
This commit is contained in:
m-holger 2024-09-16 17:59:53 +01:00 committed by GitHub
commit ddfa3a24f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 59 additions and 65 deletions

View File

@ -1061,7 +1061,7 @@ class QPDF
QPDFObjectHandle readObjectInStream(std::shared_ptr<InputSource>& input, int obj);
size_t recoverStreamLength(
std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset);
QPDFTokenizer::Token readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
QPDFTokenizer::Token readToken(InputSource&, size_t max_len = 0);
QPDFObjectHandle readObjectAtOffset(
bool attempt_recovery,
@ -1088,14 +1088,11 @@ class QPDF
qpdf_offset_t end_before_space,
qpdf_offset_t end_after_space);
static QPDFExc damagedPDF(
std::shared_ptr<InputSource> const& input,
InputSource& input,
std::string const& object,
qpdf_offset_t offset,
std::string const& message);
QPDFExc damagedPDF(
std::shared_ptr<InputSource> const& input,
qpdf_offset_t offset,
std::string const& message);
QPDFExc damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message);
QPDFExc damagedPDF(std::string const& object, qpdf_offset_t offset, std::string const& message);
QPDFExc damagedPDF(std::string const& object, std::string const& message);
QPDFExc damagedPDF(qpdf_offset_t offset, std::string const& message);

View File

@ -419,7 +419,7 @@ QPDF::findHeader()
bool
QPDF::findStartxref()
{
if (readToken(m->file).isWord("startxref") && readToken(m->file).isInteger()) {
if (readToken(*m->file).isWord("startxref") && readToken(*m->file).isInteger()) {
// Position in front of offset token
m->file->seek(m->file->getLastOffset(), SEEK_SET);
return true;
@ -457,7 +457,7 @@ QPDF::parse(char const* password)
PatternFinder sf(*this, &QPDF::findStartxref);
qpdf_offset_t xref_offset = 0;
if (m->file->findLast("startxref", start_offset, 0, sf)) {
xref_offset = QUtil::string_to_ll(readToken(m->file).getValue().c_str());
xref_offset = QUtil::string_to_ll(readToken(*m->file).getValue().c_str());
}
try {
@ -575,12 +575,12 @@ QPDF::reconstruct_xref(QPDFExc& e)
// Don't allow very long tokens here during recovery. All the interesting tokens are covered.
static size_t const MAX_LEN = 10;
while (m->file->tell() < eof) {
QPDFTokenizer::Token t1 = readToken(m->file, MAX_LEN);
QPDFTokenizer::Token t1 = readToken(*m->file, MAX_LEN);
qpdf_offset_t token_start = m->file->tell() - toO(t1.getValue().length());
if (t1.isInteger()) {
auto pos = m->file->tell();
QPDFTokenizer::Token t2 = readToken(m->file, MAX_LEN);
if ((t2.isInteger()) && (readToken(m->file, MAX_LEN).isWord("obj"))) {
QPDFTokenizer::Token t2 = readToken(*m->file, MAX_LEN);
if ((t2.isInteger()) && (readToken(*m->file, MAX_LEN).isWord("obj"))) {
int obj = QUtil::string_to_int(t1.getValue().c_str());
int gen = QUtil::string_to_int(t2.getValue().c_str());
if (obj <= m->xref_table_max_id) {
@ -989,7 +989,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
}
}
qpdf_offset_t pos = m->file->tell();
if (readToken(m->file).isWord("trailer")) {
if (readToken(*m->file).isWord("trailer")) {
break;
} else {
m->file->seek(pos, SEEK_SET);
@ -1465,12 +1465,12 @@ QPDF::readTrailer()
qpdf_offset_t offset = m->file->tell();
bool empty = false;
auto object =
QPDFParser(m->file, "trailer", m->tokenizer, nullptr, this, true).parse(empty, false);
QPDFParser(*m->file, "trailer", m->tokenizer, nullptr, this, true).parse(empty, false);
if (empty) {
// Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
// actual PDF files and Adobe Reader appears to ignore them.
warn(damagedPDF("trailer", "empty object treated as null"));
} else if (object.isDictionary() && readToken(m->file).isWord("stream")) {
} else if (object.isDictionary() && readToken(*m->file).isWord("stream")) {
warn(damagedPDF("trailer", m->file->tell(), "stream keyword found in trailer"));
}
// 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& description, QPDFObjGen og)
StringDecrypter decrypter{this, og};
StringDecrypter* decrypter_ptr = m->encp->encrypted ? &decrypter : nullptr;
auto object =
QPDFParser(m->file, m->last_object_description, m->tokenizer, decrypter_ptr, this, true)
QPDFParser(*m->file, m->last_object_description, m->tokenizer, decrypter_ptr, this, true)
.parse(empty, false);
if (empty) {
// Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
// actual PDF files and Adobe Reader appears to ignore them.
warn(damagedPDF(m->file, m->file->getLastOffset(), "empty object treated as null"));
warn(damagedPDF(*m->file, m->file->getLastOffset(), "empty object treated as null"));
return object;
}
auto token = readToken(m->file);
auto token = readToken(*m->file);
if (object.isDictionary() && token.isWord("stream")) {
readStream(object, og, offset);
token = readToken(m->file);
token = readToken(*m->file);
}
if (!token.isWord("endobj")) {
QTC::TC("qpdf", "QPDF err expected endobj");
@ -1535,7 +1535,7 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
// Seek in two steps to avoid potential integer overflow
m->file->seek(stream_offset, SEEK_SET);
m->file->seek(toO(length), SEEK_CUR);
if (!readToken(m->file).isWord("endstream")) {
if (!readToken(*m->file).isWord("endstream")) {
QTC::TC("qpdf", "QPDF missing endstream");
throw damagedPDF("expected endstream");
}
@ -1608,12 +1608,12 @@ QPDF::readObjectInStream(std::shared_ptr<InputSource>& input, int obj)
m->last_object_description += " 0";
bool empty = false;
auto object = QPDFParser(input, m->last_object_description, m->tokenizer, nullptr, this, true)
auto object = QPDFParser(*input, m->last_object_description, m->tokenizer, nullptr, this, true)
.parse(empty, false);
if (empty) {
// Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
// actual PDF files and Adobe Reader appears to ignore them.
warn(damagedPDF(input, input->getLastOffset(), "empty object treated as null"));
warn(damagedPDF(*input, input->getLastOffset(), "empty object treated as null"));
}
return object;
}
@ -1622,7 +1622,7 @@ bool
QPDF::findEndstream()
{
// Find endstream or endobj. Position the input at that token.
auto t = readToken(m->file, 20);
auto t = readToken(*m->file, 20);
if (t.isWord("endobj") || t.isWord("endstream")) {
m->file->seek(m->file->getLastOffset(), SEEK_SET);
return true;
@ -1635,14 +1635,14 @@ QPDF::recoverStreamLength(
std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset)
{
// Try to reconstruct stream length by looking for endstream or endobj
warn(damagedPDF(input, stream_offset, "attempting to recover stream length"));
warn(damagedPDF(*input, stream_offset, "attempting to recover stream length"));
PatternFinder ef(*this, &QPDF::findEndstream);
size_t length = 0;
if (m->file->findFirst("end", stream_offset, 0, ef)) {
length = toS(m->file->tell() - stream_offset);
// Reread endstream but, if it was endobj, don't skip that.
QPDFTokenizer::Token t = readToken(m->file);
QPDFTokenizer::Token t = readToken(*m->file);
if (t.getValue() == "endobj") {
m->file->seek(m->file->getLastOffset(), SEEK_SET);
}
@ -1674,10 +1674,10 @@ QPDF::recoverStreamLength(
if (length == 0) {
warn(damagedPDF(
input, stream_offset, "unable to recover stream data; treating stream as empty"));
*input, stream_offset, "unable to recover stream data; treating stream as empty"));
} else {
warn(
damagedPDF(input, stream_offset, "recovered stream length: " + std::to_string(length)));
warn(damagedPDF(
*input, stream_offset, "recovered stream length: " + std::to_string(length)));
}
QTC::TC("qpdf", "QPDF recovered stream length");
@ -1685,7 +1685,7 @@ QPDF::recoverStreamLength(
}
QPDFTokenizer::Token
QPDF::readToken(std::shared_ptr<InputSource> input, size_t max_len)
QPDF::readToken(InputSource& input, size_t max_len)
{
return m->tokenizer.readToken(input, m->last_object_description, true, max_len);
}
@ -1728,20 +1728,20 @@ QPDF::readObjectAtOffset(
m->file->seek(offset, SEEK_SET);
try {
QPDFTokenizer::Token tobjid = readToken(m->file);
QPDFTokenizer::Token tobjid = readToken(*m->file);
bool objidok = tobjid.isInteger();
QTC::TC("qpdf", "QPDF check objid", objidok ? 1 : 0);
if (!objidok) {
QTC::TC("qpdf", "QPDF expected n n obj");
throw damagedPDF(offset, "expected n n obj");
}
QPDFTokenizer::Token tgen = readToken(m->file);
QPDFTokenizer::Token tgen = readToken(*m->file);
bool genok = tgen.isInteger();
QTC::TC("qpdf", "QPDF check generation", genok ? 1 : 0);
if (!genok) {
throw damagedPDF(offset, "expected n n obj");
}
QPDFTokenizer::Token tobj = readToken(m->file);
QPDFTokenizer::Token tobj = readToken(*m->file);
bool objok = tobj.isWord("obj");
QTC::TC("qpdf", "QPDF check obj", objok ? 1 : 0);
@ -1954,11 +1954,11 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
bp.get()));
for (int i = 0; i < n; ++i) {
QPDFTokenizer::Token tnum = readToken(input);
QPDFTokenizer::Token toffset = readToken(input);
QPDFTokenizer::Token tnum = readToken(*input);
QPDFTokenizer::Token toffset = readToken(*input);
if (!(tnum.isInteger() && toffset.isInteger())) {
throw damagedPDF(
input,
*input,
m->last_object_description,
input->getLastOffset(),
"expected integer in object stream header");
@ -1972,7 +1972,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
if (num == obj_stream_number) {
QTC::TC("qpdf", "QPDF ignore self-referential object stream");
warn(damagedPDF(
input,
*input,
m->last_object_description,
input->getLastOffset(),
"object stream claims to contain itself"));
@ -2726,7 +2726,7 @@ QPDF::pipeStreamData(
file->seek(offset, SEEK_SET);
auto buf = std::make_unique<char[]>(length);
if (auto read = file->read(buf.get(), length); read != length) {
throw damagedPDF(file, "", offset + toO(read), "unexpected EOF reading stream data");
throw damagedPDF(*file, "", offset + toO(read), "unexpected EOF reading stream data");
}
pipeline->write(buf.get(), length);
attempted_finish = true;
@ -2742,7 +2742,7 @@ QPDF::pipeStreamData(
qpdf_for_warning.warn(
// line-break
damagedPDF(
file,
*file,
"",
file->getLastOffset(),
("error decoding stream data for object " + og.unparse(' ') + ": " +
@ -2751,7 +2751,7 @@ QPDF::pipeStreamData(
qpdf_for_warning.warn(
// line-break
damagedPDF(
file,
*file,
"",
file->getLastOffset(),
"stream will be re-processed without filtering to avoid data loss"));
@ -2825,19 +2825,15 @@ QPDF::stopOnError(std::string const& message)
// Return an exception of type qpdf_e_damaged_pdf.
QPDFExc
QPDF::damagedPDF(
std::shared_ptr<InputSource> const& input,
std::string const& object,
qpdf_offset_t offset,
std::string const& message)
InputSource& input, std::string const& object, qpdf_offset_t offset, std::string const& message)
{
return {qpdf_e_damaged_pdf, input->getName(), object, offset, message};
return {qpdf_e_damaged_pdf, input.getName(), object, offset, message};
}
// Return an exception of type qpdf_e_damaged_pdf. The object is taken from
// m->last_object_description.
QPDFExc
QPDF::damagedPDF(
std::shared_ptr<InputSource> const& input, qpdf_offset_t offset, std::string const& message)
QPDF::damagedPDF(InputSource& input, qpdf_offset_t offset, std::string const& message)
{
return damagedPDF(input, m->last_object_description, offset, message);
}

View File

@ -2164,7 +2164,7 @@ QPDFObjectHandle::parseContentStream_data(
qpdf_offset_t offset = input->getLastOffset();
input->seek(offset, SEEK_SET);
auto obj =
QPDFParser(input, "content", tokenizer, nullptr, context, false).parse(empty, true);
QPDFParser(*input, "content", tokenizer, nullptr, context, false).parse(empty, true);
if (!obj.isInitialized()) {
// EOF
break;
@ -2223,7 +2223,7 @@ QPDFObjectHandle::parse(
StringDecrypter* decrypter,
QPDF* context)
{
return QPDFParser(input, object_description, tokenizer, decrypter, context, false)
return QPDFParser(*input, object_description, tokenizer, decrypter, context, false)
.parse(empty, false);
}

View File

@ -33,9 +33,9 @@ QPDFParser::parse(bool& empty, bool content_stream)
QPDF::ParseGuard pg(context);
empty = false;
start = input->tell();
start = input.tell();
if (!tokenizer.nextToken(*input, object_description)) {
if (!tokenizer.nextToken(input, object_description)) {
warn(tokenizer.getErrorMessage());
}
@ -101,7 +101,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
} else if (value == "endobj") {
// We just saw endobj without having read anything. Treat this as a null and do
// not move the input source's offset.
input->seek(input->getLastOffset(), SEEK_SET);
input.seek(input.getLastOffset(), SEEK_SET);
empty = true;
return {QPDF_Null::create()};
} else {
@ -138,7 +138,7 @@ QPDFParser::parseRemainder(bool content_stream)
bool b_contents = false;
while (true) {
if (!tokenizer.nextToken(*input, object_description)) {
if (!tokenizer.nextToken(input, object_description)) {
warn(tokenizer.getErrorMessage());
}
++good_count; // optimistically
@ -151,7 +151,7 @@ QPDFParser::parseRemainder(bool content_stream)
// Process the oldest buffered integer.
addInt(int_count);
}
last_offset_buffer[int_count % 2] = input->getLastOffset();
last_offset_buffer[int_count % 2] = input.getLastOffset();
int_buffer[int_count % 2] = QUtil::string_to_ll(tokenizer.getValue().c_str());
continue;
@ -309,7 +309,7 @@ QPDFParser::parseRemainder(bool content_stream)
case QPDFTokenizer::tt_integer:
if (!content_stream) {
// Buffer token in case it is part of an indirect reference.
last_offset_buffer[1] = input->getLastOffset();
last_offset_buffer[1] = input.getLastOffset();
int_buffer[1] = QUtil::string_to_ll(tokenizer.getValue().c_str());
int_count = 1;
} else {
@ -351,7 +351,7 @@ QPDFParser::parseRemainder(bool content_stream)
if (decrypter) {
if (b_contents) {
frame->contents_string = val;
frame->contents_offset = input->getLastOffset();
frame->contents_offset = input.getLastOffset();
b_contents = false;
}
std::string s{val};
@ -419,7 +419,7 @@ void
QPDFParser::addScalar(Args&&... args)
{
auto obj = T::create(args...);
obj->setDescription(context, description, input->getLastOffset());
obj->setDescription(context, description, input.getLastOffset());
add(std::move(obj));
}
@ -506,11 +506,11 @@ QPDFParser::warnDuplicateKey()
void
QPDFParser::warn(qpdf_offset_t offset, std::string const& msg) const
{
warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(), object_description, offset, msg));
warn(QPDFExc(qpdf_e_damaged_pdf, input.getName(), object_description, offset, msg));
}
void
QPDFParser::warn(std::string const& msg) const
{
warn(input->getLastOffset(), msg);
warn(input.getLastOffset(), msg);
}

View File

@ -118,9 +118,10 @@ QPDF::isLinearized()
++p;
}
QPDFTokenizer::Token t1 = readToken(m->file);
if (t1.isInteger() && readToken(m->file).isInteger() && readToken(m->file).isWord("obj") &&
(readToken(m->file).getType() == QPDFTokenizer::tt_dict_open)) {
QPDFTokenizer::Token t1 = readToken(*m->file);
if (t1.isInteger() && readToken(*m->file).isInteger() &&
readToken(*m->file).isWord("obj") &&
readToken(*m->file).getType() == QPDFTokenizer::tt_dict_open) {
lindict_obj = toI(QUtil::string_to_ll(t1.getValue().c_str()));
}
}

View File

@ -12,7 +12,7 @@ class QPDFParser
public:
QPDFParser() = delete;
QPDFParser(
std::shared_ptr<InputSource> input,
InputSource& input,
std::string const& object_description,
QPDFTokenizer& tokenizer,
QPDFObjectHandle::StringDecrypter* decrypter,
@ -24,7 +24,7 @@ class QPDFParser
decrypter(decrypter),
context(context),
description(std::make_shared<QPDFValue::Description>(
std::string(input->getName() + ", " + object_description + " at offset $PO"))),
std::string(input.getName() + ", " + object_description + " at offset $PO"))),
parse_pdf(parse_pdf)
{
}
@ -39,9 +39,9 @@ class QPDFParser
struct StackFrame
{
StackFrame(std::shared_ptr<InputSource> const& input, parser_state_e state) :
StackFrame(InputSource& input, parser_state_e state) :
state(state),
offset(input->tell())
offset(input.tell())
{
}
@ -72,7 +72,7 @@ class QPDFParser
// NB the offset includes any leading whitespace.
QPDFObjectHandle withDescription(Args&&... args);
void setDescription(std::shared_ptr<QPDFObject>& obj, qpdf_offset_t parsed_offset);
std::shared_ptr<InputSource> input;
InputSource& input;
std::string const& object_description;
QPDFTokenizer& tokenizer;
QPDFObjectHandle::StringDecrypter* decrypter;