2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 10:58:58 +00:00

Fix linearization for files with nonstandard ID length

This commit is contained in:
Jay Berkenbilt 2018-02-04 18:02:56 -05:00
parent 9732de7ea4
commit e3167c1a60
7 changed files with 72 additions and 10 deletions

View File

@ -414,6 +414,7 @@ class QPDFWriter
void initializeSpecialStreams();
void preserveObjectStreams();
void generateObjectStreams();
std::string getOriginalID1();
void generateID();
void interpretR3EncryptionParameters(
std::set<int>& bits_to_clear,

View File

@ -1246,8 +1246,28 @@ QPDFWriter::writeTrailer(trailer_e which, int size, bool xref_stream,
writeString(" /ID [");
if (linearization_pass == 1)
{
writeString("<00000000000000000000000000000000>"
"<00000000000000000000000000000000>");
std::string original_id1 = getOriginalID1();
if (original_id1.empty())
{
writeString("<00000000000000000000000000000000>");
}
else
{
// Write a string of zeroes equal in length to the
// representation of the original ID. While writing the
// original ID would have the same number of bytes, it
// would cause a change to the deterministic ID generated
// by older versions of the software that hard-coded the
// length of the ID to 16 bytes.
writeString("<");
size_t len = QPDF_String(original_id1).unparse(true).length() - 2;
for (size_t i = 0; i < len; ++i)
{
writeString("0");
}
writeString(">");
}
writeString("<00000000000000000000000000000000>");
}
else
{
@ -1952,6 +1972,20 @@ QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index)
}
}
std::string
QPDFWriter::getOriginalID1()
{
QPDFObjectHandle trailer = this->m->pdf.getTrailer();
if (trailer.hasKey("/ID"))
{
return trailer.getKey("/ID").getArrayItem(0).getStringValue();
}
else
{
return "";
}
}
void
QPDFWriter::generateID()
{
@ -2042,12 +2076,9 @@ QPDFWriter::generateID()
// generated ID for both.
this->m->id2 = result;
if (trailer.hasKey("/ID"))
{
// Note: keep /ID from old file even if --static-id was given.
this->m->id1 = trailer.getKey("/ID").getArrayItem(0).getStringValue();
}
else
// Note: keep /ID from old file even if --static-id was given.
this->m->id1 = getOriginalID1();
if (this->m->id1.empty())
{
this->m->id1 = this->m->id2;
}

View File

@ -240,7 +240,7 @@ foreach my $d (@bug_tests)
show_ntests();
# ----------
$td->notify("--- Miscellaneous Tests ---");
$n_tests += 87;
$n_tests += 93;
$td->runtest("qpdf version",
{$td->COMMAND => "qpdf --version"},
@ -303,7 +303,8 @@ $td->runtest("check output",
{$td->FILE => "unreferenced-indirect-scalar.out"});
# Encrypt files whose /ID strings are other than 32 bytes long (bug
# 2991412).
# 2991412). Also linearize these files, which was reported in a
# separate bug by email.
foreach my $file (qw(short-id long-id))
{
$td->runtest("encrypt $file.pdf",
@ -318,6 +319,23 @@ foreach my $file (qw(short-id long-id))
{$td->FILE => "$file-check.out",
$td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("linearize $file.pdf",
{$td->COMMAND =>
"qpdf --deterministic-id --linearize $file.pdf a.pdf"},
{$td->STRING => "",
$td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("check output",
{$td->FILE => "a.pdf"},
{$td->FILE => "$file-linearized.pdf"});
$td->runtest("check $file.pdf",
{$td->COMMAND => "qpdf --check a.pdf"},
{$td->FILE => "$file-linearized-check.out",
$td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
}
# Handle file with invalid xref table and object 0 as a regular object

View File

@ -0,0 +1,6 @@
checking a.pdf
PDF Version: 1.3
File is not encrypted
File is linearized
No syntax or stream encoding errors found; the file may still contain
errors that qpdf cannot detect

Binary file not shown.

View File

@ -0,0 +1,6 @@
checking a.pdf
PDF Version: 1.3
File is not encrypted
File is linearized
No syntax or stream encoding errors found; the file may still contain
errors that qpdf cannot detect

Binary file not shown.