mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 02:49:00 +00:00
Merge pull request #1171 from m-holger/unresolved
Refactor the creation of unresolved objects
This commit is contained in:
commit
6aa6c01303
@ -133,6 +133,8 @@ set(CORPUS_OTHER
|
||||
70055.fuzz
|
||||
70245.fuzz
|
||||
70306.fuzz
|
||||
70306a.fuzz
|
||||
70306b.fuzz
|
||||
)
|
||||
|
||||
set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus)
|
||||
|
BIN
fuzz/qpdf_extra/70306a.fuzz
Normal file
BIN
fuzz/qpdf_extra/70306a.fuzz
Normal file
Binary file not shown.
BIN
fuzz/qpdf_extra/70306b.fuzz
Normal file
BIN
fuzz/qpdf_extra/70306b.fuzz
Normal file
Binary file not shown.
@ -21,7 +21,7 @@ my @fuzzers = (
|
||||
['pngpredictor' => 1],
|
||||
['runlength' => 6],
|
||||
['tiffpredictor' => 2],
|
||||
['qpdf' => 75], # increment when adding new files
|
||||
['qpdf' => 77], # increment when adding new files
|
||||
);
|
||||
|
||||
my $n_tests = 0;
|
||||
|
@ -819,7 +819,8 @@ class QPDF
|
||||
}
|
||||
};
|
||||
|
||||
// The ParseGuard class allows QPDFParser to detect re-entrant parsing.
|
||||
// The ParseGuard class allows QPDFParser to detect re-entrant parsing. It also provides
|
||||
// special access to allow the parser to create unresolved objects and dangling references.
|
||||
class ParseGuard
|
||||
{
|
||||
friend class QPDFParser;
|
||||
@ -832,6 +833,13 @@ class QPDF
|
||||
qpdf->inParse(true);
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<QPDFObject>
|
||||
getObject(QPDF* qpdf, int id, int gen, bool parse_pdf)
|
||||
{
|
||||
return qpdf->getObjectForParser(id, gen, parse_pdf);
|
||||
}
|
||||
|
||||
~ParseGuard()
|
||||
{
|
||||
if (qpdf) {
|
||||
@ -900,8 +908,8 @@ class QPDF
|
||||
}
|
||||
ObjCache(
|
||||
std::shared_ptr<QPDFObject> object,
|
||||
qpdf_offset_t end_before_space,
|
||||
qpdf_offset_t end_after_space) :
|
||||
qpdf_offset_t end_before_space = 0,
|
||||
qpdf_offset_t end_after_space = 0) :
|
||||
object(object),
|
||||
end_before_space(end_before_space),
|
||||
end_after_space(end_after_space)
|
||||
@ -1065,13 +1073,14 @@ class QPDF
|
||||
QPDFObject* resolve(QPDFObjGen og);
|
||||
void resolveObjectsInStream(int obj_stream_number);
|
||||
void stopOnError(std::string const& message);
|
||||
QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
|
||||
QPDFObjectHandle reserveStream(QPDFObjGen const& og);
|
||||
QPDFObjGen nextObjGen();
|
||||
QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
|
||||
QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);
|
||||
bool isCached(QPDFObjGen const& og);
|
||||
bool isUnresolved(QPDFObjGen const& og);
|
||||
std::shared_ptr<QPDFObject> getObjectForParser(int id, int gen, bool parse_pdf);
|
||||
std::shared_ptr<QPDFObject> getObjectForJSON(int id, int gen);
|
||||
void removeObject(QPDFObjGen og);
|
||||
void updateCache(
|
||||
QPDFObjGen const& og,
|
||||
|
@ -654,9 +654,11 @@ QPDF::reconstruct_xref(QPDFExc& e)
|
||||
}
|
||||
check_warnings();
|
||||
if (!m->parsed) {
|
||||
m->parsed = true;
|
||||
getAllPages();
|
||||
check_warnings();
|
||||
if (m->all_pages.empty()) {
|
||||
m->parsed = false;
|
||||
throw damagedPDF("", 0, "unable to find any pages while recovering damaged file");
|
||||
}
|
||||
}
|
||||
@ -1462,7 +1464,8 @@ QPDF::readTrailer()
|
||||
{
|
||||
qpdf_offset_t offset = m->file->tell();
|
||||
bool empty = false;
|
||||
auto object = QPDFParser(m->file, "trailer", m->tokenizer, nullptr, this).parse(empty, false);
|
||||
auto object =
|
||||
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.
|
||||
@ -1484,8 +1487,9 @@ 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)
|
||||
.parse(empty, false);
|
||||
auto object =
|
||||
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.
|
||||
@ -1604,7 +1608,7 @@ 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)
|
||||
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
|
||||
@ -2093,31 +2097,53 @@ QPDF::newStream(std::string const& data)
|
||||
return result;
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDF::reserveObjectIfNotExists(QPDFObjGen const& og)
|
||||
{
|
||||
if (!isCached(og) && m->xref_table.count(og) == 0) {
|
||||
updateCache(og, QPDF_Reserved::create(), -1, -1);
|
||||
return newIndirect(og, m->obj_cache[og].object);
|
||||
} else {
|
||||
return getObject(og);
|
||||
}
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDF::reserveStream(QPDFObjGen const& og)
|
||||
{
|
||||
return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
QPDF::getObjectForParser(int id, int gen, bool parse_pdf)
|
||||
{
|
||||
// This method is called by the parser and therefore must not resolve any objects.
|
||||
auto og = QPDFObjGen(id, gen);
|
||||
if (auto iter = m->obj_cache.find(og); iter != m->obj_cache.end()) {
|
||||
return iter->second.object;
|
||||
}
|
||||
if (m->xref_table.count(og) || !m->parsed) {
|
||||
return m->obj_cache.insert({og, QPDF_Unresolved::create(this, og)}).first->second.object;
|
||||
}
|
||||
if (parse_pdf) {
|
||||
return QPDF_Null::create();
|
||||
}
|
||||
return m->obj_cache.insert({og, QPDF_Null::create(this, og)}).first->second.object;
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
QPDF::getObjectForJSON(int id, int gen)
|
||||
{
|
||||
auto og = QPDFObjGen(id, gen);
|
||||
auto [it, inserted] = m->obj_cache.try_emplace(og);
|
||||
auto& obj = it->second.object;
|
||||
if (inserted) {
|
||||
obj = (m->parsed && !m->xref_table.count(og)) ? QPDF_Null::create(this, og)
|
||||
: QPDF_Unresolved::create(this, og);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDF::getObject(QPDFObjGen const& og)
|
||||
{
|
||||
// This method is called by the parser and therefore must not resolve any objects.
|
||||
if (!isCached(og)) {
|
||||
m->obj_cache[og] = ObjCache(QPDF_Unresolved::create(this, og), -1, -1);
|
||||
if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) {
|
||||
return {it->second.object};
|
||||
} else if (m->parsed && !m->xref_table.count(og)) {
|
||||
return QPDF_Null::create();
|
||||
} else {
|
||||
auto result = m->obj_cache.try_emplace(og, QPDF_Unresolved::create(this, og), -1, -1);
|
||||
return {result.first->second.object};
|
||||
}
|
||||
return newIndirect(og, m->obj_cache[og].object);
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
|
@ -2146,7 +2146,8 @@ QPDFObjectHandle::parseContentStream_data(
|
||||
tokenizer.readToken(input, "content", true);
|
||||
qpdf_offset_t offset = input->getLastOffset();
|
||||
input->seek(offset, SEEK_SET);
|
||||
auto obj = QPDFParser(input, "content", tokenizer, nullptr, context).parse(empty, true);
|
||||
auto obj =
|
||||
QPDFParser(input, "content", tokenizer, nullptr, context, false).parse(empty, true);
|
||||
if (!obj.isInitialized()) {
|
||||
// EOF
|
||||
break;
|
||||
@ -2205,7 +2206,8 @@ QPDFObjectHandle::parse(
|
||||
StringDecrypter* decrypter,
|
||||
QPDF* context)
|
||||
{
|
||||
return QPDFParser(input, object_description, tokenizer, decrypter, context).parse(empty, false);
|
||||
return QPDFParser(input, object_description, tokenizer, decrypter, context, false)
|
||||
.parse(empty, false);
|
||||
}
|
||||
|
||||
#ifndef QPDF_FUTURE
|
||||
|
@ -71,7 +71,7 @@ QPDFOutlineDocumentHelper::resolveNamedDest(QPDFObjectHandle name)
|
||||
m->dest_dict = qpdf.getRoot().getKey("/Dests");
|
||||
}
|
||||
QTC::TC("qpdf", "QPDFOutlineDocumentHelper name named dest");
|
||||
result= m->dest_dict.getKeyIfDict(name.getName());
|
||||
result = m->dest_dict.getKeyIfDict(name.getName());
|
||||
} else if (name.isString()) {
|
||||
if (!m->names_dest) {
|
||||
auto dests = qpdf.getRoot().getKey("/Names").getKeyIfDict("/Dests");
|
||||
|
@ -166,10 +166,7 @@ QPDFParser::parseRemainder(bool content_stream)
|
||||
auto id = QIntC::to_int(int_buffer[(int_count - 1) % 2]);
|
||||
auto gen = QIntC::to_int(int_buffer[(int_count) % 2]);
|
||||
if (!(id < 1 || gen < 0 || gen >= 65535)) {
|
||||
// This action has the desirable side effect of causing dangling references
|
||||
// (references to indirect objects that don't appear in the PDF) in any parsed
|
||||
// object to appear in the object cache.
|
||||
add(std::move(context->getObject(id, gen).obj));
|
||||
add(QPDF::ParseGuard::getObject(context, id, gen, parse_pdf));
|
||||
} else {
|
||||
QTC::TC("qpdf", "QPDFParser invalid objgen");
|
||||
addNull();
|
||||
|
@ -1237,7 +1237,7 @@ bool
|
||||
QPDFWriter::willFilterStream(
|
||||
QPDFObjectHandle stream,
|
||||
bool& compress_stream, // out only
|
||||
bool& is_metadata, // out only
|
||||
bool& is_metadata, // out only
|
||||
std::shared_ptr<Buffer>* stream_data)
|
||||
{
|
||||
compress_stream = false;
|
||||
|
@ -3,15 +3,15 @@
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QPDFObject_private.hh>
|
||||
|
||||
QPDF_Null::QPDF_Null() :
|
||||
QPDFValue(::ot_null, "null")
|
||||
QPDF_Null::QPDF_Null(QPDF* qpdf, QPDFObjGen og) :
|
||||
QPDFValue(::ot_null, "null", qpdf, og)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
QPDF_Null::create()
|
||||
QPDF_Null::create(QPDF* qpdf, QPDFObjGen og)
|
||||
{
|
||||
return do_create(new QPDF_Null());
|
||||
return do_create(new QPDF_Null(qpdf, og));
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
|
@ -240,11 +240,6 @@ class QPDF::JSONReactor: public JSON::Reactor
|
||||
descr(std::make_shared<QPDFValue::Description>(
|
||||
QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), "")))
|
||||
{
|
||||
for (auto& oc: pdf.m->obj_cache) {
|
||||
if (oc.second.object->getTypeCode() == ::ot_reserved) {
|
||||
reserved.insert(oc.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
~JSONReactor() override = default;
|
||||
void dictionaryStart() override;
|
||||
@ -272,10 +267,10 @@ class QPDF::JSONReactor: public JSON::Reactor
|
||||
struct StackFrame
|
||||
{
|
||||
StackFrame(state_e state) :
|
||||
state(state){};
|
||||
state(state) {};
|
||||
StackFrame(state_e state, QPDFObjectHandle&& object) :
|
||||
state(state),
|
||||
object(object){};
|
||||
object(object) {};
|
||||
state_e state;
|
||||
QPDFObjectHandle object;
|
||||
};
|
||||
@ -305,7 +300,6 @@ class QPDF::JSONReactor: public JSON::Reactor
|
||||
bool saw_data{false};
|
||||
bool saw_datafile{false};
|
||||
bool this_stream_needs_data{false};
|
||||
std::set<QPDFObjGen> reserved;
|
||||
std::vector<StackFrame> stack;
|
||||
QPDFObjectHandle next_obj;
|
||||
state_e next_state{st_top};
|
||||
@ -416,16 +410,6 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (from_state == st_qpdf) {
|
||||
// Handle dangling indirect object references which the PDF spec says to treat as nulls.
|
||||
// It's tempting to make this an error, but that would be wrong since valid input files may
|
||||
// have these.
|
||||
for (auto& oc: pdf.m->obj_cache) {
|
||||
if (oc.second.object->getTypeCode() == ::ot_reserved && reserved.count(oc.first) == 0) {
|
||||
QTC::TC("qpdf", "QPDF_json non-trivial null reserved");
|
||||
pdf.updateCache(oc.first, QPDF_Null::create(), -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!stack.empty()) {
|
||||
auto state = stack.back().state;
|
||||
@ -565,7 +549,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
|
||||
} else if (is_obj_key(key, obj, gen)) {
|
||||
this->cur_object = key;
|
||||
if (setNextStateIfDictionary(key, value, st_object_top)) {
|
||||
next_obj = pdf.reserveObjectIfNotExists(QPDFObjGen(obj, gen));
|
||||
next_obj = pdf.getObjectForJSON(obj, gen);
|
||||
}
|
||||
} else {
|
||||
QTC::TC("qpdf", "QPDF_json bad object key");
|
||||
@ -767,7 +751,7 @@ QPDF::JSONReactor::makeObject(JSON const& value)
|
||||
int gen = 0;
|
||||
std::string str;
|
||||
if (is_indirect_object(str_v, obj, gen)) {
|
||||
result = pdf.reserveObjectIfNotExists(QPDFObjGen(obj, gen));
|
||||
result = pdf.getObjectForJSON(obj, gen);
|
||||
} else if (is_unicode_string(str_v, str)) {
|
||||
result = QPDFObjectHandle::newUnicodeString(str);
|
||||
} else if (is_binary_string(str_v, str)) {
|
||||
|
@ -16,14 +16,16 @@ class QPDFParser
|
||||
std::string const& object_description,
|
||||
QPDFTokenizer& tokenizer,
|
||||
QPDFObjectHandle::StringDecrypter* decrypter,
|
||||
QPDF* context) :
|
||||
QPDF* context,
|
||||
bool parse_pdf) :
|
||||
input(input),
|
||||
object_description(object_description),
|
||||
tokenizer(tokenizer),
|
||||
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)
|
||||
{
|
||||
}
|
||||
virtual ~QPDFParser() = default;
|
||||
@ -76,6 +78,8 @@ class QPDFParser
|
||||
QPDFObjectHandle::StringDecrypter* decrypter;
|
||||
QPDF* context;
|
||||
std::shared_ptr<QPDFValue::Description> description;
|
||||
bool parse_pdf;
|
||||
|
||||
std::vector<StackFrame> stack;
|
||||
StackFrame* frame;
|
||||
// Number of recent bad tokens.
|
||||
|
@ -7,7 +7,7 @@ class QPDF_Null: public QPDFValue
|
||||
{
|
||||
public:
|
||||
~QPDF_Null() override = default;
|
||||
static std::shared_ptr<QPDFObject> create();
|
||||
static std::shared_ptr<QPDFObject> create(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen());
|
||||
static std::shared_ptr<QPDFObject> create(
|
||||
std::shared_ptr<QPDFObject> parent,
|
||||
std::string_view const& static_descr,
|
||||
@ -21,7 +21,7 @@ class QPDF_Null: public QPDFValue
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
|
||||
private:
|
||||
QPDF_Null();
|
||||
QPDF_Null(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen());
|
||||
};
|
||||
|
||||
#endif // QPDF_NULL_HH
|
||||
|
@ -16,7 +16,7 @@ struct _qpdf_data
|
||||
_qpdf_data() = default;
|
||||
|
||||
_qpdf_data(std::unique_ptr<QPDF>&& qpdf) :
|
||||
qpdf(std::move(qpdf)){};
|
||||
qpdf(std::move(qpdf)) {};
|
||||
|
||||
~_qpdf_data() = default;
|
||||
|
||||
|
@ -90,17 +90,17 @@ main()
|
||||
|
||||
obj = QPDF_Array::create({10, "null"_qpdf.getObj()}, true);
|
||||
QPDF_Array& b = *obj->as<QPDF_Array>();
|
||||
b.setAt(5, pdf.getObject(5, 0));
|
||||
b.setAt(5, pdf.newIndirectNull());
|
||||
b.setAt(7, "[0 1 2 3]"_qpdf);
|
||||
assert(b.at(3).isNull());
|
||||
assert(b.at(8).isNull());
|
||||
assert(b.at(5).isIndirect());
|
||||
assert(b.unparse() == "[ null null null null null 5 0 R null [ 0 1 2 3 ] null null ]");
|
||||
assert(b.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]");
|
||||
auto c = b.copy(true);
|
||||
auto d = b.copy(false);
|
||||
b.at(7).setArrayItem(2, "42"_qpdf);
|
||||
assert(c->unparse() == "[ null null null null null 5 0 R null [ 0 1 42 3 ] null null ]");
|
||||
assert(d->unparse() == "[ null null null null null 5 0 R null [ 0 1 2 3 ] null null ]");
|
||||
assert(c->unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]");
|
||||
assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]");
|
||||
|
||||
try {
|
||||
b.setAt(3, {});
|
||||
|
@ -675,7 +675,6 @@ QPDF_json ignore second-level key 0
|
||||
QPDF_json ignore unknown key in object_top 0
|
||||
QPDF_json ignore unknown key in trailer 0
|
||||
QPDF_json ignore unknown key in stream 0
|
||||
QPDF_json non-trivial null reserved 0
|
||||
QPDF_json data and datafile 0
|
||||
QPDF_json no stream data in update mode 0
|
||||
QPDF_json updating existing stream 0
|
||||
|
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
WARNING: dangling-bad-xref.pdf: file is damaged
|
||||
WARNING: dangling-bad-xref.pdf (object 7 0, offset 10000): expected n n obj
|
||||
WARNING: dangling-bad-xref.pdf: Attempting to reconstruct cross-reference table
|
||||
new object: 13 0 R
|
||||
new object: 12 0 R
|
||||
all objects
|
||||
1 0 R
|
||||
2 0 R
|
||||
@ -10,10 +10,6 @@ all objects
|
||||
5 0 R
|
||||
6 0 R
|
||||
7 0 R
|
||||
8 0 R
|
||||
9 0 R
|
||||
10 0 R
|
||||
11 0 R
|
||||
12 0 R
|
||||
13 0 R
|
||||
test 53 done
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
new object: 11 0 R
|
||||
new object: 8 0 R
|
||||
all objects
|
||||
1 0 R
|
||||
2 0 R
|
||||
@ -8,7 +8,4 @@ all objects
|
||||
6 0 R
|
||||
7 0 R
|
||||
8 0 R
|
||||
9 0 R
|
||||
10 0 R
|
||||
11 0 R
|
||||
test 53 done
|
||||
|
@ -7,5 +7,5 @@
|
||||
/nesting is direct
|
||||
/strings is direct
|
||||
unparse: 7 0 R
|
||||
unparseResolved: << /dangling-ref-for-json-test [ 9 0 R ] /hex#20strings [ (Potato) <01020300040560> (AB) ] /indirect 8 0 R /names [ /nesting /hex#20strings /text#2fplain ] /nesting << /a [ 1 2 << /x (y) >> [ (z) ] ] /b << / (legal) /a [ 1 2 ] >> >> /strings [ (one) <24a2> () (\(\)) (\() (\)) (a\f\b\t\r\nb) (") ("") ("\("\)") <410042> (a\nb) (a b) <efbbbfcf80> <efbbbff09fa594> ] >>
|
||||
unparseResolved: << /dangling-ref-for-json-test [ null ] /hex#20strings [ (Potato) <01020300040560> (AB) ] /indirect 8 0 R /names [ /nesting /hex#20strings /text#2fplain ] /nesting << /a [ 1 2 << /x (y) >> [ (z) ] ] /b << / (legal) /a [ 1 2 ] >> >> /strings [ (one) <24a2> () (\(\)) (\() (\)) (a\f\b\t\r\nb) (") ("") ("\("\)") <410042> (a\nb) (a b) <efbbbfcf80> <efbbbff09fa594> ] >>
|
||||
test 1 done
|
||||
|
@ -14,14 +14,14 @@ endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/dangling-ref-for-json-test [
|
||||
4 0 R
|
||||
null
|
||||
]
|
||||
/hex#20strings [
|
||||
(Potato)
|
||||
<01020300040560>
|
||||
(AB)
|
||||
]
|
||||
/indirect 5 0 R
|
||||
/indirect 4 0 R
|
||||
/names [
|
||||
/nesting
|
||||
/hex#20strings
|
||||
@ -71,27 +71,22 @@ endobj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
6 0 R
|
||||
5 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 9 0
|
||||
4 0 obj
|
||||
null
|
||||
endobj
|
||||
|
||||
%% Original object ID: 8 0
|
||||
5 0 obj
|
||||
4 0 obj
|
||||
(hello)
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
%% Original object ID: 3 0
|
||||
6 0 obj
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 7 0 R
|
||||
/Contents 6 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
@ -101,9 +96,9 @@ endobj
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 9 0 R
|
||||
/F1 8 0 R
|
||||
>>
|
||||
/ProcSet 10 0 R
|
||||
/ProcSet 9 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
@ -111,9 +106,9 @@ endobj
|
||||
|
||||
%% Contents for page 1
|
||||
%% Original object ID: 4 0
|
||||
7 0 obj
|
||||
6 0 obj
|
||||
<<
|
||||
/Length 8 0 R
|
||||
/Length 7 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
@ -124,12 +119,12 @@ ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
7 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
%% Original object ID: 6 0
|
||||
9 0 obj
|
||||
8 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
@ -140,7 +135,7 @@ endobj
|
||||
endobj
|
||||
|
||||
%% Original object ID: 5 0
|
||||
10 0 obj
|
||||
9 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
@ -148,24 +143,23 @@ endobj
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0 10
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000756 00000 n
|
||||
0000000855 00000 n
|
||||
0000000903 00000 n
|
||||
0000000964 00000 n
|
||||
0000001207 00000 n
|
||||
0000001306 00000 n
|
||||
0000001352 00000 n
|
||||
0000001497 00000 n
|
||||
0000000755 00000 n
|
||||
0000000854 00000 n
|
||||
0000000915 00000 n
|
||||
0000001157 00000 n
|
||||
0000001256 00000 n
|
||||
0000001302 00000 n
|
||||
0000001447 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 11
|
||||
/Size 10
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1533
|
||||
1482
|
||||
%%EOF
|
||||
|
@ -5,7 +5,7 @@
|
||||
item 2 is direct
|
||||
item 3 is indirect
|
||||
item 4 is direct
|
||||
item 5 is indirect
|
||||
item 5 is direct
|
||||
unparse: 9 0 R
|
||||
unparseResolved: [ /literal null /indirect 8 0 R /undefined 10 0 R ]
|
||||
unparseResolved: [ /literal null /indirect 8 0 R /undefined null ]
|
||||
test 1 done
|
||||
|
@ -18,7 +18,7 @@ endobj
|
||||
/indirect
|
||||
4 0 R
|
||||
/undefined
|
||||
5 0 R
|
||||
null
|
||||
]
|
||||
endobj
|
||||
|
||||
@ -27,7 +27,7 @@ endobj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
6 0 R
|
||||
5 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
@ -38,16 +38,11 @@ endobj
|
||||
null
|
||||
endobj
|
||||
|
||||
%% Original object ID: 10 0
|
||||
5 0 obj
|
||||
null
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
%% Original object ID: 3 0
|
||||
6 0 obj
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 7 0 R
|
||||
/Contents 6 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
@ -57,9 +52,9 @@ endobj
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 9 0 R
|
||||
/F1 8 0 R
|
||||
>>
|
||||
/ProcSet 10 0 R
|
||||
/ProcSet 9 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
@ -67,9 +62,9 @@ endobj
|
||||
|
||||
%% Contents for page 1
|
||||
%% Original object ID: 4 0
|
||||
7 0 obj
|
||||
6 0 obj
|
||||
<<
|
||||
/Length 8 0 R
|
||||
/Length 7 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
@ -80,12 +75,12 @@ ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
7 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
%% Original object ID: 6 0
|
||||
9 0 obj
|
||||
8 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
@ -96,7 +91,7 @@ endobj
|
||||
endobj
|
||||
|
||||
%% Original object ID: 7 0
|
||||
10 0 obj
|
||||
9 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
@ -104,24 +99,23 @@ endobj
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0 10
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000239 00000 n
|
||||
0000000338 00000 n
|
||||
0000000387 00000 n
|
||||
0000000445 00000 n
|
||||
0000000688 00000 n
|
||||
0000000787 00000 n
|
||||
0000000833 00000 n
|
||||
0000000978 00000 n
|
||||
0000000238 00000 n
|
||||
0000000337 00000 n
|
||||
0000000395 00000 n
|
||||
0000000637 00000 n
|
||||
0000000736 00000 n
|
||||
0000000782 00000 n
|
||||
0000000927 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 11
|
||||
/Size 10
|
||||
/ID [<06c2c8fc54c5f9cc9246898e1e1a7146><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1014
|
||||
962
|
||||
%%EOF
|
||||
|
@ -14,14 +14,14 @@ endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/dangling-ref-for-json-test [
|
||||
4 0 R
|
||||
null
|
||||
]
|
||||
/hex#20strings [
|
||||
(Potato)
|
||||
<01020300040560>
|
||||
(AB)
|
||||
]
|
||||
/indirect 5 0 R
|
||||
/indirect 4 0 R
|
||||
/names [
|
||||
/nesting
|
||||
/hex#20strings
|
||||
@ -71,27 +71,22 @@ endobj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
6 0 R
|
||||
5 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 9 0
|
||||
4 0 obj
|
||||
null
|
||||
endobj
|
||||
|
||||
%% Original object ID: 8 0
|
||||
5 0 obj
|
||||
4 0 obj
|
||||
(hello)
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
%% Original object ID: 3 0
|
||||
6 0 obj
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 7 0 R
|
||||
/Contents 6 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
@ -101,9 +96,9 @@ endobj
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 9 0 R
|
||||
/F1 8 0 R
|
||||
>>
|
||||
/ProcSet 10 0 R
|
||||
/ProcSet 9 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
@ -111,9 +106,9 @@ endobj
|
||||
|
||||
%% Contents for page 1
|
||||
%% Original object ID: 4 0
|
||||
7 0 obj
|
||||
6 0 obj
|
||||
<<
|
||||
/Length 8 0 R
|
||||
/Length 7 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
@ -124,12 +119,12 @@ ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
7 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
%% Original object ID: 6 0
|
||||
9 0 obj
|
||||
8 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
@ -140,7 +135,7 @@ endobj
|
||||
endobj
|
||||
|
||||
%% Original object ID: 5 0
|
||||
10 0 obj
|
||||
9 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
@ -148,24 +143,23 @@ endobj
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0 10
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000752 00000 n
|
||||
0000000851 00000 n
|
||||
0000000899 00000 n
|
||||
0000000960 00000 n
|
||||
0000001203 00000 n
|
||||
0000001302 00000 n
|
||||
0000001348 00000 n
|
||||
0000001493 00000 n
|
||||
0000000751 00000 n
|
||||
0000000850 00000 n
|
||||
0000000911 00000 n
|
||||
0000001153 00000 n
|
||||
0000001252 00000 n
|
||||
0000001298 00000 n
|
||||
0000001443 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 11
|
||||
/Size 10
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1529
|
||||
1478
|
||||
%%EOF
|
||||
|
@ -14,14 +14,14 @@ endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/dangling-ref-for-json-test [
|
||||
4 0 R
|
||||
null
|
||||
]
|
||||
/hex#20strings [
|
||||
(Potato)
|
||||
<01020300040560>
|
||||
(AB)
|
||||
]
|
||||
/indirect 5 0 R
|
||||
/indirect 4 0 R
|
||||
/names [
|
||||
/nesting
|
||||
/hex#20strings
|
||||
@ -71,37 +71,32 @@ endobj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
7 0 R
|
||||
6 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 9 0
|
||||
4 0 obj
|
||||
null
|
||||
endobj
|
||||
|
||||
%% Original object ID: 8 0
|
||||
5 0 obj
|
||||
4 0 obj
|
||||
<<
|
||||
/K /V
|
||||
/Length 6 0 R
|
||||
/Length 5 0 R
|
||||
>>
|
||||
stream
|
||||
new-stream-here
|
||||
endstream
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
5 0 obj
|
||||
16
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
%% Original object ID: 3 0
|
||||
7 0 obj
|
||||
6 0 obj
|
||||
<<
|
||||
/Contents 8 0 R
|
||||
/Contents 7 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
@ -111,9 +106,9 @@ endobj
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 10 0 R
|
||||
/F1 9 0 R
|
||||
>>
|
||||
/ProcSet 11 0 R
|
||||
/ProcSet 10 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
@ -121,9 +116,9 @@ endobj
|
||||
|
||||
%% Contents for page 1
|
||||
%% Original object ID: 4 0
|
||||
8 0 obj
|
||||
7 0 obj
|
||||
<<
|
||||
/Length 9 0 R
|
||||
/Length 8 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
@ -134,12 +129,12 @@ ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
8 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
%% Original object ID: 6 0
|
||||
10 0 obj
|
||||
9 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
@ -150,7 +145,7 @@ endobj
|
||||
endobj
|
||||
|
||||
%% Original object ID: 5 0
|
||||
11 0 obj
|
||||
10 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
@ -158,25 +153,24 @@ endobj
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 12
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000756 00000 n
|
||||
0000000855 00000 n
|
||||
0000000903 00000 n
|
||||
0000000982 00000 n
|
||||
0000001038 00000 n
|
||||
0000001282 00000 n
|
||||
0000001381 00000 n
|
||||
0000001427 00000 n
|
||||
0000001573 00000 n
|
||||
0000000755 00000 n
|
||||
0000000854 00000 n
|
||||
0000000933 00000 n
|
||||
0000000989 00000 n
|
||||
0000001232 00000 n
|
||||
0000001331 00000 n
|
||||
0000001377 00000 n
|
||||
0000001522 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 12
|
||||
/Size 11
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1609
|
||||
1558
|
||||
%%EOF
|
||||
|
@ -14,14 +14,14 @@ endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/dangling-ref-for-json-test [
|
||||
4 0 R
|
||||
null
|
||||
]
|
||||
/hex#20strings [
|
||||
(Potato)
|
||||
<01020300040560>
|
||||
(AB)
|
||||
]
|
||||
/indirect 5 0 R
|
||||
/indirect 4 0 R
|
||||
/names [
|
||||
/nesting
|
||||
/hex#20strings
|
||||
@ -71,27 +71,22 @@ endobj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
6 0 R
|
||||
5 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 9 0
|
||||
4 0 obj
|
||||
null
|
||||
endobj
|
||||
|
||||
%% Original object ID: 8 0
|
||||
5 0 obj
|
||||
4 0 obj
|
||||
(hello)
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
%% Original object ID: 3 0
|
||||
6 0 obj
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 7 0 R
|
||||
/Contents 6 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
@ -101,9 +96,9 @@ endobj
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 9 0 R
|
||||
/F1 8 0 R
|
||||
>>
|
||||
/ProcSet 10 0 R
|
||||
/ProcSet 9 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
@ -111,9 +106,9 @@ endobj
|
||||
|
||||
%% Contents for page 1
|
||||
%% Original object ID: 4 0
|
||||
7 0 obj
|
||||
6 0 obj
|
||||
<<
|
||||
/Length 8 0 R
|
||||
/Length 7 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
@ -124,12 +119,12 @@ ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
7 0 obj
|
||||
43
|
||||
endobj
|
||||
|
||||
%% Original object ID: 6 0
|
||||
9 0 obj
|
||||
8 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
@ -140,7 +135,7 @@ endobj
|
||||
endobj
|
||||
|
||||
%% Original object ID: 5 0
|
||||
10 0 obj
|
||||
9 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
@ -148,24 +143,23 @@ endobj
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0 10
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000756 00000 n
|
||||
0000000855 00000 n
|
||||
0000000903 00000 n
|
||||
0000000964 00000 n
|
||||
0000001207 00000 n
|
||||
0000001305 00000 n
|
||||
0000001351 00000 n
|
||||
0000001496 00000 n
|
||||
0000000755 00000 n
|
||||
0000000854 00000 n
|
||||
0000000915 00000 n
|
||||
0000001157 00000 n
|
||||
0000001255 00000 n
|
||||
0000001301 00000 n
|
||||
0000001446 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 11
|
||||
/Size 10
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1532
|
||||
1481
|
||||
%%EOF
|
||||
|
@ -14,14 +14,14 @@ endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/dangling-ref-for-json-test [
|
||||
4 0 R
|
||||
null
|
||||
]
|
||||
/hex#20strings [
|
||||
(Potato)
|
||||
<01020300040560>
|
||||
(AB)
|
||||
]
|
||||
/indirect 5 0 R
|
||||
/indirect 4 0 R
|
||||
/names [
|
||||
/nesting
|
||||
/hex#20strings
|
||||
@ -71,27 +71,22 @@ endobj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
6 0 R
|
||||
5 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 9 0
|
||||
4 0 obj
|
||||
null
|
||||
endobj
|
||||
|
||||
%% Original object ID: 8 0
|
||||
5 0 obj
|
||||
4 0 obj
|
||||
(hello)
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
%% Original object ID: 3 0
|
||||
6 0 obj
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 7 0 R
|
||||
/Contents 6 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
@ -101,9 +96,9 @@ endobj
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 9 0 R
|
||||
/F1 8 0 R
|
||||
>>
|
||||
/ProcSet 10 0 R
|
||||
/ProcSet 9 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
@ -111,10 +106,10 @@ endobj
|
||||
|
||||
%% Contents for page 1
|
||||
%% Original object ID: 4 0
|
||||
7 0 obj
|
||||
6 0 obj
|
||||
<<
|
||||
/Potato (salad)
|
||||
/Length 8 0 R
|
||||
/Length 7 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
@ -125,12 +120,12 @@ ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
7 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
%% Original object ID: 6 0
|
||||
9 0 obj
|
||||
8 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
@ -141,7 +136,7 @@ endobj
|
||||
endobj
|
||||
|
||||
%% Original object ID: 5 0
|
||||
10 0 obj
|
||||
9 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
@ -149,24 +144,23 @@ endobj
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0 10
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000756 00000 n
|
||||
0000000855 00000 n
|
||||
0000000903 00000 n
|
||||
0000000964 00000 n
|
||||
0000001207 00000 n
|
||||
0000001324 00000 n
|
||||
0000001370 00000 n
|
||||
0000001515 00000 n
|
||||
0000000755 00000 n
|
||||
0000000854 00000 n
|
||||
0000000915 00000 n
|
||||
0000001157 00000 n
|
||||
0000001274 00000 n
|
||||
0000001320 00000 n
|
||||
0000001465 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 11
|
||||
/Size 10
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1551
|
||||
1500
|
||||
%%EOF
|
||||
|
Loading…
Reference in New Issue
Block a user