Commit 78fc0d1b3b65b4c77e3836f3a3dd585aeb83fdfa

Authored by m-holger
1 parent c5efd0c3

Refactor `QPDF_encryption::decryptStream`: streamline handling of `/Type` and `/…

…DecodeParms` using `Name`, `Dictionary`, and `Array` for improved clarity and consistency, and remove unused test coverage entries.
libqpdf/QPDF_encryption.cc
@@ -931,12 +931,7 @@ QPDF::decryptStream( @@ -931,12 +931,7 @@ QPDF::decryptStream(
931 bool is_root_metadata, 931 bool is_root_metadata,
932 std::unique_ptr<Pipeline>& decrypt_pipeline) 932 std::unique_ptr<Pipeline>& decrypt_pipeline)
933 { 933 {
934 - std::string type;  
935 - if (stream_dict.getKey("/Type").isName()) {  
936 - type = stream_dict.getKey("/Type").getName();  
937 - }  
938 - if (type == "/XRef") {  
939 - QTC::TC("qpdf", "QPDF_encryption xref stream from encrypted file"); 934 + if (Name(stream_dict["/Type"]) == "/XRef") {
940 return; 935 return;
941 } 936 }
942 bool use_aes = false; 937 bool use_aes = false;
@@ -945,26 +940,20 @@ QPDF::decryptStream( @@ -945,26 +940,20 @@ QPDF::decryptStream(
945 std::string method_source = "/StmF from /Encrypt dictionary"; 940 std::string method_source = "/StmF from /Encrypt dictionary";
946 941
947 if (stream_dict.getKey("/Filter").isOrHasName("/Crypt")) { 942 if (stream_dict.getKey("/Filter").isOrHasName("/Crypt")) {
948 - if (stream_dict.getKey("/DecodeParms").isDictionary()) {  
949 - QPDFObjectHandle decode_parms = stream_dict.getKey("/DecodeParms");  
950 - if (decode_parms.isDictionaryOfType("/CryptFilterDecodeParms")) {  
951 - QTC::TC("qpdf", "QPDF_encryption stream crypt filter");  
952 - method = encp->interpretCF(decode_parms.getKey("/Name")); 943 + if (Dictionary decode_parms = stream_dict["/DecodeParms"]) {
  944 + if (Name(decode_parms["/Type"]) == "/CryptFilterDecodeParms") {
  945 + method = encp->interpretCF(decode_parms["/Name"]);
953 method_source = "stream's Crypt decode parameters"; 946 method_source = "stream's Crypt decode parameters";
954 } 947 }
955 - } else if (  
956 - stream_dict.getKey("/DecodeParms").isArray() &&  
957 - stream_dict.getKey("/Filter").isArray()) {  
958 - auto filter = stream_dict.getKey("/Filter");  
959 - auto decode = stream_dict.getKey("/DecodeParms"); 948 + } else {
  949 + Array filter = stream_dict["/Filter"];
  950 + Array decode = stream_dict.getKey("/DecodeParms");
960 if (filter.size() == decode.size()) { 951 if (filter.size() == decode.size()) {
961 - int i = 0;  
962 - for (auto const& item: filter.as_array()) {  
963 - if (item.isNameAndEquals("/Crypt")) {  
964 - auto crypt_params = decode.getArrayItem(i);  
965 - if (crypt_params.isDictionary() &&  
966 - crypt_params.getKey("/Name").isName()) {  
967 - method = encp->interpretCF(crypt_params.getKey("/Name")); 952 + size_t i = 0;
  953 + for (Name item: filter) {
  954 + if (item == "/Crypt") {
  955 + if (Name name = decode[i]["/Name"]) {
  956 + method = encp->interpretCF(name);
968 method_source = "stream's Crypt decode parameters (array)"; 957 method_source = "stream's Crypt decode parameters (array)";
969 } 958 }
970 break; 959 break;
@@ -976,8 +965,7 @@ QPDF::decryptStream( @@ -976,8 +965,7 @@ QPDF::decryptStream(
976 } 965 }
977 966
978 if (method == e_unknown) { 967 if (method == e_unknown) {
979 - if ((!encp->encrypt_metadata) && is_root_metadata) {  
980 - QTC::TC("qpdf", "QPDF_encryption cleartext metadata"); 968 + if (!encp->encrypt_metadata && is_root_metadata) {
981 method = e_none; 969 method = e_none;
982 } else { 970 } else {
983 method = encp->cf_stream; 971 method = encp->cf_stream;
@@ -1002,13 +990,13 @@ QPDF::decryptStream( @@ -1002,13 +990,13 @@ QPDF::decryptStream(
1002 990
1003 default: 991 default:
1004 // filter local to this stream. 992 // filter local to this stream.
1005 - qpdf_for_warning.warn(QPDFExc(  
1006 - qpdf_e_damaged_pdf,  
1007 - file->getName(),  
1008 - "",  
1009 - file->getLastOffset(),  
1010 - "unknown encryption filter for streams (check " + method_source +  
1011 - "); streams may be decrypted improperly")); 993 + qpdf_for_warning.warn(
  994 + {qpdf_e_damaged_pdf,
  995 + file->getName(),
  996 + "",
  997 + file->getLastOffset(),
  998 + "unknown encryption filter for streams (check " + method_source +
  999 + "); streams may be decrypted improperly"});
1012 // To avoid repeated warnings, reset cf_stream. Assume we'd want to use AES if V == 4. 1000 // To avoid repeated warnings, reset cf_stream. Assume we'd want to use AES if V == 4.
1013 encp->cf_stream = e_aes; 1001 encp->cf_stream = e_aes;
1014 use_aes = true; 1002 use_aes = true;
@@ -1017,11 +1005,9 @@ QPDF::decryptStream( @@ -1017,11 +1005,9 @@ QPDF::decryptStream(
1017 } 1005 }
1018 std::string key = getKeyForObject(encp, og, use_aes); 1006 std::string key = getKeyForObject(encp, og, use_aes);
1019 if (use_aes) { 1007 if (use_aes) {
1020 - QTC::TC("qpdf", "QPDF_encryption aes decode stream");  
1021 decrypt_pipeline = 1008 decrypt_pipeline =
1022 std::make_unique<Pl_AES_PDF>("AES stream decryption", pipeline, false, key); 1009 std::make_unique<Pl_AES_PDF>("AES stream decryption", pipeline, false, key);
1023 } else { 1010 } else {
1024 - QTC::TC("qpdf", "QPDF_encryption rc4 decode stream");  
1025 decrypt_pipeline = std::make_unique<Pl_RC4>("RC4 stream decryption", pipeline, key); 1011 decrypt_pipeline = std::make_unique<Pl_RC4>("RC4 stream decryption", pipeline, key);
1026 } 1012 }
1027 pipeline = decrypt_pipeline.get(); 1013 pipeline = decrypt_pipeline.get();
qpdf/qpdf.testcov
@@ -96,7 +96,6 @@ QPDF recovered stream length 0 @@ -96,7 +96,6 @@ QPDF recovered stream length 0
96 QPDF found wrong endstream in recovery 0 96 QPDF found wrong endstream in recovery 0
97 QPDF_Stream pipeStreamData with null pipeline 0 97 QPDF_Stream pipeStreamData with null pipeline 0
98 QPDFWriter not recompressing /FlateDecode 0 98 QPDFWriter not recompressing /FlateDecode 0
99 -QPDF_encryption xref stream from encrypted file 0  
100 QPDFJob unable to filter 0 99 QPDFJob unable to filter 0
101 QUtil non-trivial UTF-16 0 100 QUtil non-trivial UTF-16 0
102 QPDF xref overwrite invalid objgen 0 101 QPDF xref overwrite invalid objgen 0
@@ -141,16 +140,12 @@ qpdf-c called qpdf_set_minimum_pdf_version 0 @@ -141,16 +140,12 @@ qpdf-c called qpdf_set_minimum_pdf_version 0
141 qpdf-c called qpdf_force_pdf_version 0 140 qpdf-c called qpdf_force_pdf_version 0
142 qpdf-c called qpdf_init_write multiple times 0 141 qpdf-c called qpdf_init_write multiple times 0
143 QPDF_encryption rc4 decode string 0 142 QPDF_encryption rc4 decode string 0
144 -QPDF_encryption rc4 decode stream 0  
145 QPDFWriter not compressing metadata 0 143 QPDFWriter not compressing metadata 0
146 QPDF_encryption aes decode string 0 144 QPDF_encryption aes decode string 0
147 -QPDF_encryption cleartext metadata 0  
148 -QPDF_encryption aes decode stream 0  
149 QPDFWriter forcing object stream disable 0 145 QPDFWriter forcing object stream disable 0
150 QPDFWriter forced version disabled encryption 0 146 QPDFWriter forced version disabled encryption 0
151 qpdf-c called qpdf_set_r4_encryption_parameters_insecure 0 147 qpdf-c called qpdf_set_r4_encryption_parameters_insecure 0
152 qpdf-c called qpdf_set_static_aes_IV 0 148 qpdf-c called qpdf_set_static_aes_IV 0
153 -QPDF_encryption stream crypt filter 0  
154 QPDF ERR object stream with wrong type 0 149 QPDF ERR object stream with wrong type 0
155 QPDF object gone after xref reconstruction 0 150 QPDF object gone after xref reconstruction 0
156 qpdf-c called qpdf_has_error 0 151 qpdf-c called qpdf_has_error 0