mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 19:08:59 +00:00
Refactor QPDF::Objects / JSONReactor interaction
Allow for the fact that when processing JSON input we cannot determine whether references are dangling until the whole input has been processed. We handle this by optimistically storing references in the object table. When additional gens are encountered for the same object we store them in the new map unconfirmed_objects. Once processing is complete we clean up the object table and clear unconfirmed_objects. New test cases are adapted from manual-qpdf-json.json etc.
This commit is contained in:
parent
486e68f2e5
commit
405f3765c5
@ -256,10 +256,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;
|
||||
};
|
||||
@ -422,8 +422,7 @@ QPDF::JSONReactor::replaceObject(QPDFObjectHandle&& replacement, JSON const& val
|
||||
"the value of an object may not be an indirect object reference");
|
||||
return;
|
||||
}
|
||||
pdf.replaceObject(og, replacement);
|
||||
next_obj = pdf.getObject(og);
|
||||
next_obj = pdf.m->objects.replace_when_uncertain(og.getObj(), og.getGen(), replacement);
|
||||
setObjectDescription(tos.object, value);
|
||||
}
|
||||
|
||||
@ -536,7 +535,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.objects().get_for_json(obj, gen);
|
||||
next_obj = pdf.objects().get_when_uncertain(obj, gen);
|
||||
}
|
||||
} else {
|
||||
QTC::TC("qpdf", "QPDF_json bad object key");
|
||||
@ -597,7 +596,14 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
|
||||
throw std::logic_error("stack empty in st_stream");
|
||||
}
|
||||
auto& tos = stack.back();
|
||||
|
||||
if (!tos.object.isStream()) {
|
||||
if (tos.object.isDirectNull()) {
|
||||
// Object is direct null if it has been replaced.
|
||||
saw_dict = true;
|
||||
saw_data = true;
|
||||
return true;
|
||||
}
|
||||
throw std::logic_error("current object is not stream in st_stream");
|
||||
}
|
||||
auto uninitialized = QPDFObjectHandle();
|
||||
@ -740,7 +746,7 @@ QPDF::JSONReactor::makeObject(JSON const& value)
|
||||
int gen = 0;
|
||||
std::string str;
|
||||
if (is_indirect_object(str_v, obj, gen)) {
|
||||
result = pdf.objects().get_for_json(obj, gen);
|
||||
result = pdf.objects().get_when_uncertain(obj, gen);
|
||||
} else if (is_unicode_string(str_v, str)) {
|
||||
result = QPDFObjectHandle::newUnicodeString(str);
|
||||
} else if (is_binary_string(str_v, str)) {
|
||||
@ -798,6 +804,7 @@ QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete)
|
||||
JSONReactor reactor(*this, is, must_be_complete);
|
||||
try {
|
||||
JSON::parse(*is, &reactor);
|
||||
objects().clear_unconfirmeds();
|
||||
} catch (std::runtime_error& e) {
|
||||
throw std::runtime_error(is->getName() + ": " + e.what());
|
||||
}
|
||||
|
@ -1719,7 +1719,7 @@ Objects::Entry::update(int a_gen, const std::shared_ptr<QPDFObject>& obj)
|
||||
{
|
||||
if (*this) {
|
||||
if (gen != a_gen) {
|
||||
throw std::logic_error("Internal eror in Objects::update_table");
|
||||
throw std::logic_error("Internal error in Objects::update_table");
|
||||
}
|
||||
object->assign(obj);
|
||||
} else {
|
||||
@ -1729,6 +1729,18 @@ Objects::Entry::update(int a_gen, const std::shared_ptr<QPDFObject>& obj)
|
||||
return object;
|
||||
}
|
||||
|
||||
// Reset to uninitialised state, making any object null.
|
||||
void
|
||||
Objects::Entry::reset()
|
||||
{
|
||||
if (object) {
|
||||
object->make_null();
|
||||
}
|
||||
object = nullptr;
|
||||
gen = 0;
|
||||
unconfirmed = false;
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
Objects::update_entry(Entry& e, int id, int gen, const std::shared_ptr<QPDFObject>& obj)
|
||||
{
|
||||
@ -1752,7 +1764,14 @@ bool
|
||||
Objects::unresolved(int id, int gen)
|
||||
{
|
||||
auto it = table.find(id);
|
||||
return it == table.end() || (it->second.gen == gen && it->second.object->isUnresolved());
|
||||
if (it == table.end()) {
|
||||
return true;
|
||||
}
|
||||
if (it->second.gen == gen) {
|
||||
return it->second.object->isUnresolved();
|
||||
}
|
||||
auto it2 = unconfirmed_objects.find({id, gen});
|
||||
return it2 != unconfirmed_objects.end() && it2->second->isUnresolved();
|
||||
}
|
||||
|
||||
// Increment last_id and return the result.
|
||||
@ -1789,6 +1808,23 @@ Objects::initialize()
|
||||
last_id_ = std::max(last_id_, toI(xref.size() - 1));
|
||||
}
|
||||
|
||||
void
|
||||
Objects::clear_unconfirmeds()
|
||||
{
|
||||
for (auto it = table.begin(), end = table.end(); it != end;) {
|
||||
if (it->second && it->second.unconfirmed) {
|
||||
it->second.object->make_null();
|
||||
it = table.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
for (auto& item: unconfirmed_objects) {
|
||||
item.second->make_null();
|
||||
}
|
||||
unconfirmed_objects.clear();
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
Objects::make_indirect(std::shared_ptr<QPDFObject> const& obj)
|
||||
{
|
||||
@ -1820,22 +1856,85 @@ Objects::get_for_parser(int id, int gen, bool parse_pdf)
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
Objects::get_for_json(int id, int gen)
|
||||
Objects::get_when_uncertain(int id, int gen)
|
||||
{
|
||||
auto [it, inserted] = table.try_emplace(id);
|
||||
auto& obj = it->second.object;
|
||||
if (inserted) {
|
||||
it->second.gen = gen;
|
||||
last_id_ = std::max(last_id_, id);
|
||||
obj = xref.initialized() && !xref.type(id, gen)
|
||||
? QPDF_Null::create(&qpdf, QPDFObjGen(id, gen))
|
||||
: QPDF_Unresolved::create(&qpdf, QPDFObjGen(id, gen));
|
||||
} else {
|
||||
if (it->second.gen != gen) {
|
||||
return QPDF_Null::create();
|
||||
auto& e = table[id];
|
||||
if (!e) {
|
||||
// There is no existing entry. If this (id, gen) is in the xref table, we encountered an
|
||||
// unresolved object. Otherwise we optimistically assume that it is a reference to an actual
|
||||
// object, but mark it as unconfirmed.
|
||||
if (xref.initialized()) {
|
||||
last_id_ = std::max(last_id_, id);
|
||||
}
|
||||
e.gen = gen;
|
||||
if (!xref.type(id, gen)) {
|
||||
e.unconfirmed = true;
|
||||
return e.object = QPDF_Null::create(&qpdf, QPDFObjGen(id, gen));
|
||||
} else {
|
||||
return e.object = QPDF_Unresolved::create(&qpdf, QPDFObjGen(id, gen));
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
|
||||
// Existing entry
|
||||
if (e.gen == gen) {
|
||||
return e.object;
|
||||
}
|
||||
if (!e.unconfirmed && gen < e.gen) {
|
||||
// Table contains a newer confirmed object. This (id, gen) is definitely a dangling
|
||||
// reference.
|
||||
return QPDF_Null::create();
|
||||
}
|
||||
// We don't know whether the table entry is valid, therefore this (id, gen) could still be
|
||||
// valid despite the gen mismatch. Return a shared indirect null from unconfirmed_objects.
|
||||
if (auto& j = unconfirmed_objects[{id, gen}]) {
|
||||
return j;
|
||||
} else {
|
||||
return j = QPDF_Null::create(&qpdf, QPDFObjGen(id, gen));
|
||||
}
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
Objects::replace_when_uncertain(int id, int gen, QPDFObjectHandle& oh)
|
||||
{
|
||||
// This method is only called while loading a JSON file.
|
||||
if (!id) {
|
||||
// Direct null from a reference already identified as dangling.
|
||||
return oh;
|
||||
}
|
||||
auto& e = table[id];
|
||||
|
||||
if (!e) {
|
||||
// This should not happen since the JSONReactor should have called replace_when_uncertain
|
||||
// when starting to parse the object.
|
||||
throw std::logic_error("Internal error in Objects::replace_for_json");
|
||||
}
|
||||
if (e.gen == gen) {
|
||||
e.unconfirmed = false; // Now confirmed - this is an actual object.
|
||||
return update_entry(e, id, gen, oh.getObj());
|
||||
}
|
||||
|
||||
if (e.gen < gen) {
|
||||
// The current entry will definitely be replaced by oh.
|
||||
e.object->make_null();
|
||||
} else if (!e.unconfirmed) {
|
||||
// oh has been replaced by this current entry.
|
||||
oh.getObj()->make_null();
|
||||
return oh;
|
||||
}
|
||||
|
||||
if (e.unconfirmed) {
|
||||
// The current entry could still become live by a later replace. Let's stash it away.
|
||||
unconfirmed_objects.emplace(std::pair{id, e.gen}, e.object);
|
||||
}
|
||||
|
||||
e.reset();
|
||||
// Make sure we don't clean up the actual object.
|
||||
if (auto it = unconfirmed_objects.find({id, gen}); it != unconfirmed_objects.end()) {
|
||||
e.object = it->second;
|
||||
unconfirmed_objects.erase(it); // Make sure we don't clean up the actual object.
|
||||
}
|
||||
e.gen = gen;
|
||||
return update_entry(e, id, gen, oh.getObj());
|
||||
}
|
||||
|
||||
// Replace the object with oh. In the process oh will become almost, but not quite, the indirect
|
||||
|
@ -469,11 +469,15 @@ class QPDF::Objects
|
||||
void erase(int id, int gen);
|
||||
|
||||
void replace(int id, int gen, QPDFObjectHandle oh);
|
||||
// replace for when we cannot be sure whether object references are dangling.
|
||||
QPDFObjectHandle replace_when_uncertain(int id, int gen, QPDFObjectHandle& oh);
|
||||
|
||||
void swap(QPDFObjGen og1, QPDFObjGen og2);
|
||||
|
||||
std::shared_ptr<QPDFObject> make_indirect(std::shared_ptr<QPDFObject> const& obj);
|
||||
|
||||
void clear_unconfirmeds();
|
||||
|
||||
QPDFObjectHandle read(
|
||||
bool attempt_recovery,
|
||||
qpdf_offset_t offset,
|
||||
@ -488,7 +492,9 @@ class QPDF::Objects
|
||||
int last_id();
|
||||
|
||||
std::shared_ptr<QPDFObject> get_for_parser(int id, int gen, bool parse_pdf);
|
||||
std::shared_ptr<QPDFObject> get_for_json(int id, int gen);
|
||||
|
||||
// get for when we cannot be sure whether object references are dangling.
|
||||
std::shared_ptr<QPDFObject> get_when_uncertain(int id, int gen);
|
||||
|
||||
// Get a list of objects that would be permitted in an object stream.
|
||||
template <typename T>
|
||||
@ -524,8 +530,10 @@ class QPDF::Objects
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject> update(int gen, const std::shared_ptr<QPDFObject>& obj);
|
||||
void reset();
|
||||
|
||||
int gen{0};
|
||||
bool unconfirmed{false}; // True if we are uncertain whether the entry is a dangling ref.
|
||||
std::shared_ptr<QPDFObject> object;
|
||||
}; // Entry
|
||||
|
||||
@ -553,7 +561,7 @@ class QPDF::Objects
|
||||
Xref_table xref;
|
||||
|
||||
std::map<int, Entry> table;
|
||||
|
||||
std::map<std::pair<int, int>, std::shared_ptr<QPDFObject>> unconfirmed_objects;
|
||||
bool initialized_{false};
|
||||
int last_id_{0};
|
||||
}; // Objects
|
||||
|
@ -148,7 +148,7 @@ $td->runtest("check manual JSON to JSON",
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check manual JSON to JSON to JSON",
|
||||
{$td->COMMAND => "qpdf --json-output=2 --json-input a.json -"},
|
||||
{$td->FILE => "a.json", $td->EXIT_STATUS => 0},
|
||||
{$td->FILE => "manual-qpdf-json-temporary-out.json", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$n_tests += 6;
|
||||
@ -383,5 +383,42 @@ $td->runtest("write JSON to pipeline",
|
||||
{$td->COMMAND => "test_driver 98 minimal.pdf ''"},
|
||||
{$td->STRING => "test 98 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$n_tests += 8;
|
||||
$td->runtest("manual JSON dangling refs to PDF",
|
||||
{$td->COMMAND => "qpdf --json-input --static-id --qdf" .
|
||||
" manual-qpdf-json-dangle.json a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check manual JSON dangling refs to PDF",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "manual-qpdf-json-dangle.pdf"});
|
||||
$td->runtest("check manual JSON dangling refs to PDF to JSON",
|
||||
{$td->COMMAND => "qpdf --json-output=2 a.pdf -"},
|
||||
{$td->FILE => "manual-qpdf-json-pdf-dangle.json", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("manual JSON dangling refs to JSON",
|
||||
{$td->COMMAND => "qpdf --json-input --json-output=2" .
|
||||
" manual-qpdf-json-pdf-dangle.json a.json"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check manual JSON dangling refs to JSON",
|
||||
{$td->FILE => "a.json"},
|
||||
{$td->FILE => "manual-qpdf-json-dangle-out.json"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check manual JSON dangling refs to JSON to JSON",
|
||||
{$td->COMMAND => "qpdf --json-output=2 --json-input a.json -"},
|
||||
{$td->FILE => "manual-qpdf-json-dangle-out.json", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("manual JSON replaced stream to JSON",
|
||||
{$td->COMMAND => "qpdf --json-input --json-output=2" .
|
||||
" manual-qpdf-json-bad-stream.json a.json"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check manual JSON dangling refs to JSON",
|
||||
{$td->FILE => "a.json"},
|
||||
{$td->FILE => "manual-qpdf-json-bad-stream-out.json"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
cleanup();
|
||||
$td->report($n_tests);
|
||||
|
158
qpdf/qtest/qpdf/manual-qpdf-json-bad-stream-out.json
Normal file
158
qpdf/qtest/qpdf/manual-qpdf-json-bad-stream-out.json
Normal file
@ -0,0 +1,158 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "2.0",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 100
|
||||
},
|
||||
{
|
||||
"obj:1 2 R": {
|
||||
"value": {
|
||||
"/Pages": "2 1 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:2 1 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"3 2 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
}
|
||||
},
|
||||
"obj:3 2 R": {
|
||||
"value": {
|
||||
"/Dangle": [
|
||||
null,
|
||||
null,
|
||||
"u:2 1 R is actual",
|
||||
null,
|
||||
null,
|
||||
"u:3 2 R is actual",
|
||||
null,
|
||||
null,
|
||||
"8 5 R",
|
||||
"u:8 5 R is actual, encounter gens 0, 5, 2, 7",
|
||||
null,
|
||||
"u:1 2 R is actual",
|
||||
null,
|
||||
"u:5 0 % is actual"
|
||||
],
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "2 1 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "6 0 R"
|
||||
},
|
||||
"/ProcSet": "5 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
}
|
||||
},
|
||||
"obj:4 2 R": {
|
||||
"value": {
|
||||
"/Type": "/Rubbish"
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"obj:7 0 R": {
|
||||
"value": {
|
||||
"/hex strings": [
|
||||
"u:Potato",
|
||||
"b:01020300040560",
|
||||
"u:AB"
|
||||
],
|
||||
"/names": [
|
||||
"/nesting",
|
||||
"/hex strings",
|
||||
"/text/plain"
|
||||
],
|
||||
"/nesting": {
|
||||
"/a": [
|
||||
1,
|
||||
2,
|
||||
{
|
||||
"/x": "u:y"
|
||||
},
|
||||
[
|
||||
"u:z"
|
||||
]
|
||||
],
|
||||
"/b": {
|
||||
"/": "u:legal",
|
||||
"/a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
"/strings": [
|
||||
"u:one",
|
||||
"b:24a2",
|
||||
"u:",
|
||||
"u:",
|
||||
"u:()",
|
||||
"u:(",
|
||||
"u:)",
|
||||
"u:a\f\b\t\r\nb",
|
||||
"u:\"",
|
||||
"u:\"\"",
|
||||
"u:\"(\")\"",
|
||||
"b:410042",
|
||||
"u:a\nb",
|
||||
"u:a b",
|
||||
[
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π"
|
||||
],
|
||||
[
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"obj:8 5 R": {
|
||||
"value": {
|
||||
"/dangling": [
|
||||
null
|
||||
],
|
||||
"/k1": "u:hello"
|
||||
}
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/QTest": "7 0 R",
|
||||
"/Root": "1 2 R",
|
||||
"/Size": 9
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
195
qpdf/qtest/qpdf/manual-qpdf-json-bad-stream.json
Normal file
195
qpdf/qtest/qpdf/manual-qpdf-json-bad-stream.json
Normal file
@ -0,0 +1,195 @@
|
||||
{
|
||||
"comment": [
|
||||
"File with stream 4 0 replaced by object 4 2.",
|
||||
"Modified from manual-qpdf-json-dangle.json."
|
||||
],
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "2.0",
|
||||
"maybe-future-key": {
|
||||
"x": [
|
||||
"Lots of times we ignore things",
|
||||
"for forward-compatibility so we don't have",
|
||||
"to change the version number if we add stuff",
|
||||
"in the future"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"obj:3 2 R": {
|
||||
"value": {
|
||||
"/Contents": "4 0 R",
|
||||
"/Dangle": [
|
||||
"2 0 R",
|
||||
"2 3 R",
|
||||
"u:2 1 R is actual",
|
||||
"3 3 R",
|
||||
"3 1 R",
|
||||
"u:3 2 R is actual",
|
||||
"8 7 R",
|
||||
"8 0 R",
|
||||
"8 5 R",
|
||||
"u:8 5 R is actual, encounter gens 0, 5, 2, 7",
|
||||
"1 0 R",
|
||||
"u:1 2 R is actual",
|
||||
"5 5 R",
|
||||
"u:5 0 % is actual"
|
||||
],
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "2 1 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "6 0 R"
|
||||
},
|
||||
"/ProcSet": "5 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
},
|
||||
"ignore": "this is ignored"
|
||||
},
|
||||
"obj:4 2 R": {
|
||||
"value": {
|
||||
"/Pages": "2 0 R",
|
||||
"/Type": "/Rubbish"
|
||||
}
|
||||
},
|
||||
"obj:2 1 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"3 2 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
},
|
||||
"ignore": {
|
||||
"potato": "salad",
|
||||
"this": ["is ignored too"]
|
||||
}
|
||||
},
|
||||
"obj:1 2 R": {
|
||||
"value": {
|
||||
"/Pages": "2 1 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:4 0 R": {
|
||||
"stream": {
|
||||
"what-is-this": "doesn't matter",
|
||||
"dict": {},
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo="
|
||||
}
|
||||
},
|
||||
"obj:1 1 R": {
|
||||
"value": {
|
||||
"/Pages": "2 0 R",
|
||||
"/Type": "/AlsoRubbish"
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"trailer": {
|
||||
"even-here-we-ignore": "stuff",
|
||||
"value": {
|
||||
"/QTest": "7 0 R",
|
||||
"/Root": "1 2 R",
|
||||
"/Size": 9
|
||||
}
|
||||
},
|
||||
"obj:7 0 R": {
|
||||
"value": {
|
||||
"/hex strings": [
|
||||
"u:Potato",
|
||||
"b:01020300040560",
|
||||
"u:AB"
|
||||
],
|
||||
"/indirect": "8 0 R",
|
||||
"/names": [
|
||||
"/nesting",
|
||||
"/hex strings",
|
||||
"/text/plain"
|
||||
],
|
||||
"/nesting": {
|
||||
"/a": [
|
||||
1,
|
||||
2,
|
||||
{
|
||||
"/x": "u:y"
|
||||
},
|
||||
[
|
||||
"u:z"
|
||||
]
|
||||
],
|
||||
"/b": {
|
||||
"/": "u:legal",
|
||||
"/a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
"/strings": [
|
||||
"u:one",
|
||||
"b:24a2",
|
||||
"b:",
|
||||
"u:",
|
||||
"u:()",
|
||||
"u:(",
|
||||
"u:)",
|
||||
"u:a\f\b\t\r\nb",
|
||||
"u:\"",
|
||||
"u:\"\"",
|
||||
"u:\"(\")\"",
|
||||
"b:410042",
|
||||
"u:a\nb",
|
||||
"u:a b",
|
||||
["u:π", "u:\u03c0", "b:EFBBBFCF80", "b:feff03c0"],
|
||||
["u:🥔", "u:\ud83e\udd54", "b:feffd83eDD54", "b:efbbbff09fa594"]
|
||||
]
|
||||
}
|
||||
},
|
||||
"obj:8 0 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello wrong",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
},
|
||||
"obj:8 5 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
},
|
||||
"obj:8 2 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello also wrong",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
},
|
||||
"obj:8 7 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello also wrong",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
167
qpdf/qtest/qpdf/manual-qpdf-json-dangle-out.json
Normal file
167
qpdf/qtest/qpdf/manual-qpdf-json-dangle-out.json
Normal file
@ -0,0 +1,167 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "2.0",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 9
|
||||
},
|
||||
{
|
||||
"obj:1 0 R": {
|
||||
"value": {
|
||||
"/Pages": "3 0 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:2 0 R": {
|
||||
"value": {
|
||||
"/hex strings": [
|
||||
"u:Potato",
|
||||
"b:01020300040560",
|
||||
"u:AB"
|
||||
],
|
||||
"/names": [
|
||||
"/nesting",
|
||||
"/hex strings",
|
||||
"/text/plain"
|
||||
],
|
||||
"/nesting": {
|
||||
"/a": [
|
||||
1,
|
||||
2,
|
||||
{
|
||||
"/x": "u:y"
|
||||
},
|
||||
[
|
||||
"u:z"
|
||||
]
|
||||
],
|
||||
"/b": {
|
||||
"/": "u:legal",
|
||||
"/a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
"/strings": [
|
||||
"u:one",
|
||||
"b:24a2",
|
||||
"u:",
|
||||
"u:",
|
||||
"u:()",
|
||||
"u:(",
|
||||
"u:)",
|
||||
"u:a\f\b\t\r\nb",
|
||||
"u:\"",
|
||||
"u:\"\"",
|
||||
"u:\"(\")\"",
|
||||
"b:410042",
|
||||
"u:a\nb",
|
||||
"u:a b",
|
||||
[
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π"
|
||||
],
|
||||
[
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"obj:3 0 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"4 0 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
}
|
||||
},
|
||||
"obj:4 0 R": {
|
||||
"value": {
|
||||
"/Contents": "5 0 R",
|
||||
"/Dangle": [
|
||||
null,
|
||||
null,
|
||||
"u:2 1 R is actual",
|
||||
null,
|
||||
null,
|
||||
"u:3 2 R is actual",
|
||||
null,
|
||||
null,
|
||||
"7 0 R",
|
||||
"u:8 5 R is actual, encounter gens 0, 5, 2, 7",
|
||||
null,
|
||||
"u:1 2 R is actual",
|
||||
null,
|
||||
"u:5 0 % is actual"
|
||||
],
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "3 0 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "8 0 R"
|
||||
},
|
||||
"/ProcSet": "9 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"stream": {
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
|
||||
"dict": {}
|
||||
}
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": 44
|
||||
},
|
||||
"obj:7 0 R": {
|
||||
"value": {
|
||||
"/dangling": [
|
||||
null
|
||||
],
|
||||
"/k1": "u:hello"
|
||||
}
|
||||
},
|
||||
"obj:8 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"obj:9 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/ID": [
|
||||
"b:31415926535897932384626433832795",
|
||||
"b:31415926535897932384626433832795"
|
||||
],
|
||||
"/QTest": "2 0 R",
|
||||
"/Root": "1 0 R",
|
||||
"/Size": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
195
qpdf/qtest/qpdf/manual-qpdf-json-dangle.json
Normal file
195
qpdf/qtest/qpdf/manual-qpdf-json-dangle.json
Normal file
@ -0,0 +1,195 @@
|
||||
{
|
||||
"comment": [
|
||||
"File with multiple definitions for the same object id and with dangling references.",
|
||||
"Modified from manual-qpdf-json-dangle.json."
|
||||
],
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "2.0",
|
||||
"maybe-future-key": {
|
||||
"x": [
|
||||
"Lots of times we ignore things",
|
||||
"for forward-compatibility so we don't have",
|
||||
"to change the version number if we add stuff",
|
||||
"in the future"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"obj:3 2 R": {
|
||||
"value": {
|
||||
"/Contents": "4 0 R",
|
||||
"/Dangle": [
|
||||
"2 0 R",
|
||||
"2 3 R",
|
||||
"u:2 1 R is actual",
|
||||
"3 3 R",
|
||||
"3 1 R",
|
||||
"u:3 2 R is actual",
|
||||
"8 7 R",
|
||||
"8 0 R",
|
||||
"8 5 R",
|
||||
"u:8 5 R is actual, encounter gens 0, 5, 2, 7",
|
||||
"1 0 R",
|
||||
"u:1 2 R is actual",
|
||||
"5 5 R",
|
||||
"u:5 0 % is actual"
|
||||
],
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "2 1 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "6 0 R"
|
||||
},
|
||||
"/ProcSet": "5 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
},
|
||||
"ignore": "this is ignored"
|
||||
},
|
||||
"obj:1 0 R": {
|
||||
"value": {
|
||||
"/Pages": "2 0 R",
|
||||
"/Type": "/Rubbish"
|
||||
}
|
||||
},
|
||||
"obj:2 1 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"3 2 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
},
|
||||
"ignore": {
|
||||
"potato": "salad",
|
||||
"this": ["is ignored too"]
|
||||
}
|
||||
},
|
||||
"obj:1 2 R": {
|
||||
"value": {
|
||||
"/Pages": "2 1 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:4 0 R": {
|
||||
"stream": {
|
||||
"what-is-this": "doesn't matter",
|
||||
"dict": {},
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo="
|
||||
}
|
||||
},
|
||||
"obj:1 1 R": {
|
||||
"value": {
|
||||
"/Pages": "2 0 R",
|
||||
"/Type": "/AlsoRubbish"
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"trailer": {
|
||||
"even-here-we-ignore": "stuff",
|
||||
"value": {
|
||||
"/QTest": "7 0 R",
|
||||
"/Root": "1 2 R",
|
||||
"/Size": 9
|
||||
}
|
||||
},
|
||||
"obj:7 0 R": {
|
||||
"value": {
|
||||
"/hex strings": [
|
||||
"u:Potato",
|
||||
"b:01020300040560",
|
||||
"u:AB"
|
||||
],
|
||||
"/indirect": "8 0 R",
|
||||
"/names": [
|
||||
"/nesting",
|
||||
"/hex strings",
|
||||
"/text/plain"
|
||||
],
|
||||
"/nesting": {
|
||||
"/a": [
|
||||
1,
|
||||
2,
|
||||
{
|
||||
"/x": "u:y"
|
||||
},
|
||||
[
|
||||
"u:z"
|
||||
]
|
||||
],
|
||||
"/b": {
|
||||
"/": "u:legal",
|
||||
"/a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
"/strings": [
|
||||
"u:one",
|
||||
"b:24a2",
|
||||
"b:",
|
||||
"u:",
|
||||
"u:()",
|
||||
"u:(",
|
||||
"u:)",
|
||||
"u:a\f\b\t\r\nb",
|
||||
"u:\"",
|
||||
"u:\"\"",
|
||||
"u:\"(\")\"",
|
||||
"b:410042",
|
||||
"u:a\nb",
|
||||
"u:a b",
|
||||
["u:π", "u:\u03c0", "b:EFBBBFCF80", "b:feff03c0"],
|
||||
["u:🥔", "u:\ud83e\udd54", "b:feffd83eDD54", "b:efbbbff09fa594"]
|
||||
]
|
||||
}
|
||||
},
|
||||
"obj:8 0 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello wrong",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
},
|
||||
"obj:8 5 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
},
|
||||
"obj:8 2 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello also wrong",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
},
|
||||
"obj:8 7 R": {
|
||||
"value": {
|
||||
"/k1": "u:hello also wrong",
|
||||
"/dangling": ["100 0 R"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
193
qpdf/qtest/qpdf/manual-qpdf-json-dangle.pdf
Normal file
193
qpdf/qtest/qpdf/manual-qpdf-json-dangle.pdf
Normal file
@ -0,0 +1,193 @@
|
||||
%PDF-2.0
|
||||
%¿÷¢þ
|
||||
%QDF-1.0
|
||||
|
||||
%% Original object ID: 1 2
|
||||
1 0 obj
|
||||
<<
|
||||
/Pages 3 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 7 0
|
||||
2 0 obj
|
||||
<<
|
||||
/hex#20strings [
|
||||
(Potato)
|
||||
<01020300040560>
|
||||
(AB)
|
||||
]
|
||||
/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)
|
||||
[
|
||||
<feff03c0>
|
||||
<feff03c0>
|
||||
<efbbbfcf80>
|
||||
<feff03c0>
|
||||
]
|
||||
[
|
||||
<feffd83edd54>
|
||||
<feffd83edd54>
|
||||
<feffd83edd54>
|
||||
<efbbbff09fa594>
|
||||
]
|
||||
]
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 2 1
|
||||
3 0 obj
|
||||
<<
|
||||
/Count 1
|
||||
/Kids [
|
||||
4 0 R
|
||||
]
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Page 1
|
||||
%% Original object ID: 3 2
|
||||
4 0 obj
|
||||
<<
|
||||
/Contents 5 0 R
|
||||
/Dangle [
|
||||
null
|
||||
null
|
||||
(2 1 R is actual)
|
||||
null
|
||||
null
|
||||
(3 2 R is actual)
|
||||
null
|
||||
null
|
||||
7 0 R
|
||||
(8 5 R is actual, encounter gens 0, 5, 2, 7)
|
||||
null
|
||||
(1 2 R is actual)
|
||||
null
|
||||
(5 0 % is actual)
|
||||
]
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
612
|
||||
792
|
||||
]
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 8 0 R
|
||||
>>
|
||||
/ProcSet 9 0 R
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Contents for page 1
|
||||
%% Original object ID: 4 0
|
||||
5 0 obj
|
||||
<<
|
||||
/Length 6 0 R
|
||||
>>
|
||||
stream
|
||||
BT
|
||||
/F1 24 Tf
|
||||
72 720 Td
|
||||
(Potato) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
44
|
||||
endobj
|
||||
|
||||
%% Original object ID: 8 5
|
||||
7 0 obj
|
||||
<<
|
||||
/dangling [
|
||||
null
|
||||
]
|
||||
/k1 (hello)
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 6 0
|
||||
8 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
/Name /F1
|
||||
/Subtype /Type1
|
||||
/Type /Font
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 5 0
|
||||
9 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
]
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 10
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000841 00000 n
|
||||
0000000950 00000 n
|
||||
0000001427 00000 n
|
||||
0000001526 00000 n
|
||||
0000001572 00000 n
|
||||
0000001662 00000 n
|
||||
0000001807 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 10
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1842
|
||||
%%EOF
|
@ -128,14 +128,11 @@
|
||||
"obj:8 0 R": {
|
||||
"value": {
|
||||
"/dangling": [
|
||||
"100 0 R"
|
||||
null
|
||||
],
|
||||
"/k1": "u:hello"
|
||||
}
|
||||
},
|
||||
"obj:100 0 R": {
|
||||
"value": null
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/QTest": "7 0 R",
|
||||
|
167
qpdf/qtest/qpdf/manual-qpdf-json-pdf-dangle.json
Normal file
167
qpdf/qtest/qpdf/manual-qpdf-json-pdf-dangle.json
Normal file
@ -0,0 +1,167 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "2.0",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 9
|
||||
},
|
||||
{
|
||||
"obj:1 0 R": {
|
||||
"value": {
|
||||
"/Pages": "3 0 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:2 0 R": {
|
||||
"value": {
|
||||
"/hex strings": [
|
||||
"u:Potato",
|
||||
"b:01020300040560",
|
||||
"u:AB"
|
||||
],
|
||||
"/names": [
|
||||
"/nesting",
|
||||
"/hex strings",
|
||||
"/text/plain"
|
||||
],
|
||||
"/nesting": {
|
||||
"/a": [
|
||||
1,
|
||||
2,
|
||||
{
|
||||
"/x": "u:y"
|
||||
},
|
||||
[
|
||||
"u:z"
|
||||
]
|
||||
],
|
||||
"/b": {
|
||||
"/": "u:legal",
|
||||
"/a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
"/strings": [
|
||||
"u:one",
|
||||
"b:24a2",
|
||||
"u:",
|
||||
"u:",
|
||||
"u:()",
|
||||
"u:(",
|
||||
"u:)",
|
||||
"u:a\f\b\t\r\nb",
|
||||
"u:\"",
|
||||
"u:\"\"",
|
||||
"u:\"(\")\"",
|
||||
"b:410042",
|
||||
"u:a\nb",
|
||||
"u:a b",
|
||||
[
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π"
|
||||
],
|
||||
[
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"obj:3 0 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"4 0 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
}
|
||||
},
|
||||
"obj:4 0 R": {
|
||||
"value": {
|
||||
"/Contents": "5 0 R",
|
||||
"/Dangle": [
|
||||
null,
|
||||
null,
|
||||
"u:2 1 R is actual",
|
||||
null,
|
||||
null,
|
||||
"u:3 2 R is actual",
|
||||
null,
|
||||
null,
|
||||
"7 0 R",
|
||||
"u:8 5 R is actual, encounter gens 0, 5, 2, 7",
|
||||
null,
|
||||
"u:1 2 R is actual",
|
||||
null,
|
||||
"u:5 0 % is actual"
|
||||
],
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "3 0 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "8 0 R"
|
||||
},
|
||||
"/ProcSet": "9 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"stream": {
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
|
||||
"dict": {}
|
||||
}
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": 44
|
||||
},
|
||||
"obj:7 0 R": {
|
||||
"value": {
|
||||
"/dangling": [
|
||||
null
|
||||
],
|
||||
"/k1": "u:hello"
|
||||
}
|
||||
},
|
||||
"obj:8 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"obj:9 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/ID": [
|
||||
"b:31415926535897932384626433832795",
|
||||
"b:31415926535897932384626433832795"
|
||||
],
|
||||
"/QTest": "2 0 R",
|
||||
"/Root": "1 0 R",
|
||||
"/Size": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
"pdfversion": "2.0",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 10
|
||||
"maxobjectid": 9
|
||||
},
|
||||
{
|
||||
"obj:1 0 R": {
|
||||
@ -88,14 +88,14 @@
|
||||
"obj:4 0 R": {
|
||||
"value": {
|
||||
"/dangling": [
|
||||
"6 0 R"
|
||||
null
|
||||
],
|
||||
"/k1": "u:hello"
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"value": {
|
||||
"/Contents": "7 0 R",
|
||||
"/Contents": "6 0 R",
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
@ -105,26 +105,23 @@
|
||||
"/Parent": "3 0 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "9 0 R"
|
||||
"/F1": "8 0 R"
|
||||
},
|
||||
"/ProcSet": "10 0 R"
|
||||
"/ProcSet": "9 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
}
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": null
|
||||
},
|
||||
"obj:7 0 R": {
|
||||
"stream": {
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
|
||||
"dict": {}
|
||||
}
|
||||
},
|
||||
"obj:8 0 R": {
|
||||
"obj:7 0 R": {
|
||||
"value": 44
|
||||
},
|
||||
"obj:9 0 R": {
|
||||
"obj:8 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
@ -133,7 +130,7 @@
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"obj:10 0 R": {
|
||||
"obj:9 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
@ -147,7 +144,7 @@
|
||||
],
|
||||
"/QTest": "2 0 R",
|
||||
"/Root": "1 0 R",
|
||||
"/Size": 11
|
||||
"/Size": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
145
qpdf/qtest/qpdf/manual-qpdf-json-temporary-out.json
Normal file
145
qpdf/qtest/qpdf/manual-qpdf-json-temporary-out.json
Normal file
@ -0,0 +1,145 @@
|
||||
{
|
||||
"qpdf": [
|
||||
{
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "2.0",
|
||||
"pushedinheritedpageresources": false,
|
||||
"calledgetallpages": false,
|
||||
"maxobjectid": 8
|
||||
},
|
||||
{
|
||||
"obj:1 0 R": {
|
||||
"value": {
|
||||
"/Pages": "2 0 R",
|
||||
"/Type": "/Catalog"
|
||||
}
|
||||
},
|
||||
"obj:2 0 R": {
|
||||
"value": {
|
||||
"/Count": 1,
|
||||
"/Kids": [
|
||||
"3 0 R"
|
||||
],
|
||||
"/Type": "/Pages"
|
||||
}
|
||||
},
|
||||
"obj:3 0 R": {
|
||||
"value": {
|
||||
"/Contents": "4 0 R",
|
||||
"/MediaBox": [
|
||||
0,
|
||||
0,
|
||||
612,
|
||||
792
|
||||
],
|
||||
"/Parent": "2 0 R",
|
||||
"/Resources": {
|
||||
"/Font": {
|
||||
"/F1": "6 0 R"
|
||||
},
|
||||
"/ProcSet": "5 0 R"
|
||||
},
|
||||
"/Type": "/Page"
|
||||
}
|
||||
},
|
||||
"obj:4 0 R": {
|
||||
"stream": {
|
||||
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
|
||||
"dict": {}
|
||||
}
|
||||
},
|
||||
"obj:5 0 R": {
|
||||
"value": [
|
||||
"/PDF",
|
||||
"/Text"
|
||||
]
|
||||
},
|
||||
"obj:6 0 R": {
|
||||
"value": {
|
||||
"/BaseFont": "/Helvetica",
|
||||
"/Encoding": "/WinAnsiEncoding",
|
||||
"/Name": "/F1",
|
||||
"/Subtype": "/Type1",
|
||||
"/Type": "/Font"
|
||||
}
|
||||
},
|
||||
"obj:7 0 R": {
|
||||
"value": {
|
||||
"/hex strings": [
|
||||
"u:Potato",
|
||||
"b:01020300040560",
|
||||
"u:AB"
|
||||
],
|
||||
"/indirect": "8 0 R",
|
||||
"/names": [
|
||||
"/nesting",
|
||||
"/hex strings",
|
||||
"/text/plain"
|
||||
],
|
||||
"/nesting": {
|
||||
"/a": [
|
||||
1,
|
||||
2,
|
||||
{
|
||||
"/x": "u:y"
|
||||
},
|
||||
[
|
||||
"u:z"
|
||||
]
|
||||
],
|
||||
"/b": {
|
||||
"/": "u:legal",
|
||||
"/a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
"/strings": [
|
||||
"u:one",
|
||||
"b:24a2",
|
||||
"u:",
|
||||
"u:",
|
||||
"u:()",
|
||||
"u:(",
|
||||
"u:)",
|
||||
"u:a\f\b\t\r\nb",
|
||||
"u:\"",
|
||||
"u:\"\"",
|
||||
"u:\"(\")\"",
|
||||
"b:410042",
|
||||
"u:a\nb",
|
||||
"u:a b",
|
||||
[
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π",
|
||||
"u:π"
|
||||
],
|
||||
[
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔",
|
||||
"u:🥔"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"obj:8 0 R": {
|
||||
"value": {
|
||||
"/dangling": [
|
||||
null
|
||||
],
|
||||
"/k1": "u:hello"
|
||||
}
|
||||
},
|
||||
"trailer": {
|
||||
"value": {
|
||||
"/QTest": "7 0 R",
|
||||
"/Root": "1 0 R",
|
||||
"/Size": 9
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -89,7 +89,7 @@ endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/dangling [
|
||||
6 0 R
|
||||
null
|
||||
]
|
||||
/k1 (hello)
|
||||
>>
|
||||
@ -99,7 +99,7 @@ endobj
|
||||
%% Original object ID: 3 0
|
||||
5 0 obj
|
||||
<<
|
||||
/Contents 7 0 R
|
||||
/Contents 6 0 R
|
||||
/MediaBox [
|
||||
0
|
||||
0
|
||||
@ -109,24 +109,19 @@ 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
|
||||
>>
|
||||
endobj
|
||||
|
||||
%% Original object ID: 100 0
|
||||
6 0 obj
|
||||
null
|
||||
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
|
||||
@ -137,12 +132,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
|
||||
@ -153,7 +148,7 @@ endobj
|
||||
endobj
|
||||
|
||||
%% Original object ID: 5 0
|
||||
10 0 obj
|
||||
9 0 obj
|
||||
[
|
||||
/PDF
|
||||
/Text
|
||||
@ -161,24 +156,23 @@ endobj
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0 10
|
||||
0000000000 65535 f
|
||||
0000000052 00000 n
|
||||
0000000133 00000 n
|
||||
0000000859 00000 n
|
||||
0000000958 00000 n
|
||||
0000001059 00000 n
|
||||
0000001281 00000 n
|
||||
0000001352 00000 n
|
||||
0000001451 00000 n
|
||||
0000001497 00000 n
|
||||
0000001642 00000 n
|
||||
0000001058 00000 n
|
||||
0000001300 00000 n
|
||||
0000001399 00000 n
|
||||
0000001445 00000 n
|
||||
0000001590 00000 n
|
||||
trailer <<
|
||||
/QTest 2 0 R
|
||||
/Root 1 0 R
|
||||
/Size 11
|
||||
/Size 10
|
||||
/ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
|
||||
>>
|
||||
startxref
|
||||
1678
|
||||
1625
|
||||
%%EOF
|
||||
|
Loading…
Reference in New Issue
Block a user