Commit 5508f74603d7a816ab67456939bd3ee57676f842
1 parent
b997fa53
Allow /P in encryption dictionary to be positive (fixes #382)
Even though this is disallowed by the spec, files like this have been encountered in the wild.
Showing
8 changed files
with
80 additions
and
3 deletions
ChangeLog
| 1 | +2019-11-09 Jay Berkenbilt <ejb@ql.org> | |
| 2 | + | |
| 3 | + * When reading /P from the encryption dictionary, use static_cast | |
| 4 | + instead of QIntC to convert the value to a signed integer. The | |
| 5 | + value of /P is a bit field, and PDF files have been found in the | |
| 6 | + wild where /P is represented as an unsigned integer even though | |
| 7 | + the spec states that it is a signed 32-bit value. By using | |
| 8 | + static_cast, we allow qpdf to compensate for writers that | |
| 9 | + incorrectly represent the correct bit field as an unsigned value. | |
| 10 | + Fixes #382. | |
| 11 | + | |
| 1 | 12 | 2019-11-05 Jay Berkenbilt <ejb@ql.org> |
| 2 | 13 | |
| 3 | 14 | * Add support for pluggable crypto providers, enabling multiple | ... | ... |
libqpdf/QPDFPageObjectHelper.cc
| ... | ... | @@ -661,6 +661,7 @@ QPDFPageObjectHelper::getFormXObjectForPage(bool handle_transformations) |
| 661 | 661 | return result; |
| 662 | 662 | } |
| 663 | 663 | |
| 664 | +// ABI: name should be std:string const& | |
| 664 | 665 | std::string |
| 665 | 666 | QPDFPageObjectHelper::placeFormXObject( |
| 666 | 667 | QPDFObjectHandle fo, std::string name, | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -762,7 +762,7 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf) |
| 762 | 762 | V, |
| 763 | 763 | encrypt.getKey("/R").getIntValueAsInt(), |
| 764 | 764 | key_len, |
| 765 | - encrypt.getKey("/P").getIntValueAsInt(), | |
| 765 | + static_cast<int>(encrypt.getKey("/P").getIntValue()), | |
| 766 | 766 | encrypt.getKey("/O").getStringValue(), |
| 767 | 767 | encrypt.getKey("/U").getStringValue(), |
| 768 | 768 | OE, | ... | ... |
libqpdf/QPDF_encryption.cc
| ... | ... | @@ -877,7 +877,7 @@ QPDF::initializeEncryption() |
| 877 | 877 | int R = encryption_dict.getKey("/R").getIntValueAsInt(); |
| 878 | 878 | std::string O = encryption_dict.getKey("/O").getStringValue(); |
| 879 | 879 | std::string U = encryption_dict.getKey("/U").getStringValue(); |
| 880 | - int P = encryption_dict.getKey("/P").getIntValueAsInt(); | |
| 880 | + int P = static_cast<int>(encryption_dict.getKey("/P").getIntValue()); | |
| 881 | 881 | |
| 882 | 882 | // If supporting new encryption R/V values, remember to update |
| 883 | 883 | // error message inside this if statement. |
| ... | ... | @@ -1448,7 +1448,7 @@ QPDF::isEncrypted(int& R, int& P, int& V, |
| 1448 | 1448 | QPDFObjectHandle Pkey = encrypt.getKey("/P"); |
| 1449 | 1449 | QPDFObjectHandle Rkey = encrypt.getKey("/R"); |
| 1450 | 1450 | QPDFObjectHandle Vkey = encrypt.getKey("/V"); |
| 1451 | - P = Pkey.getIntValueAsInt(); | |
| 1451 | + P = static_cast<int>(Pkey.getIntValue()); | |
| 1452 | 1452 | R = Rkey.getIntValueAsInt(); |
| 1453 | 1453 | V = Vkey.getIntValueAsInt(); |
| 1454 | 1454 | stream_method = this->m->encp->cf_stream; | ... | ... |
qpdf/qtest/qpdf.test
| ... | ... | @@ -721,6 +721,32 @@ foreach my $d (@bug_tests) |
| 721 | 721 | } |
| 722 | 722 | show_ntests(); |
| 723 | 723 | # ---------- |
| 724 | +$td->notify("--- Positive /P in encryption dictionary ---"); | |
| 725 | +$n_tests += 4; | |
| 726 | + | |
| 727 | +# Files have been seen where /P in the encryption dictionary was an | |
| 728 | +# unsigned rather than a signed integer. To create | |
| 729 | +# encrypted-positive-P.pdf, I temporarily modified QPDFWriter.cc to | |
| 730 | +# introduce this error. | |
| 731 | + | |
| 732 | +$td->runtest("decrypt positive P", | |
| 733 | + {$td->COMMAND => | |
| 734 | + "qpdf --decrypt --static-id encrypted-positive-P.pdf a.pdf"}, | |
| 735 | + {$td->STRING => "", $td->EXIT_STATUS => 0}); | |
| 736 | +$td->runtest("check output", | |
| 737 | + {$td->FILE => "a.pdf"}, | |
| 738 | + {$td->FILE => "decrypted-positive-P.pdf"}); | |
| 739 | +$td->runtest("copy encryption positive P", | |
| 740 | + {$td->COMMAND => | |
| 741 | + "qpdf --static-id --static-aes-iv" . | |
| 742 | + " encrypted-positive-P.pdf a.pdf"}, | |
| 743 | + {$td->STRING => "", $td->EXIT_STATUS => 0}); | |
| 744 | +$td->runtest("check output", | |
| 745 | + {$td->FILE => "a.pdf"}, | |
| 746 | + {$td->FILE => "copied-positive-P.pdf"}); | |
| 747 | + | |
| 748 | +show_ntests(); | |
| 749 | +# ---------- | |
| 724 | 750 | $td->notify("--- Library version ---"); |
| 725 | 751 | $n_tests += 3; |
| 726 | 752 | ... | ... |
qpdf/qtest/qpdf/copied-positive-P.pdf
0 โ 100644
No preview for this file type
qpdf/qtest/qpdf/decrypted-positive-P.pdf
0 โ 100644
No preview for this file type
qpdf/qtest/qpdf/encrypted-positive-P.pdf
0 โ 100644
No preview for this file type