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 931 bool is_root_metadata,
932 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 935 return;
941 936 }
942 937 bool use_aes = false;
... ... @@ -945,26 +940,20 @@ QPDF::decryptStream(
945 940 std::string method_source = "/StmF from /Encrypt dictionary";
946 941  
947 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 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 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 957 method_source = "stream's Crypt decode parameters (array)";
969 958 }
970 959 break;
... ... @@ -976,8 +965,7 @@ QPDF::decryptStream(
976 965 }
977 966  
978 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 969 method = e_none;
982 970 } else {
983 971 method = encp->cf_stream;
... ... @@ -1002,13 +990,13 @@ QPDF::decryptStream(
1002 990  
1003 991 default:
1004 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 1000 // To avoid repeated warnings, reset cf_stream. Assume we'd want to use AES if V == 4.
1013 1001 encp->cf_stream = e_aes;
1014 1002 use_aes = true;
... ... @@ -1017,11 +1005,9 @@ QPDF::decryptStream(
1017 1005 }
1018 1006 std::string key = getKeyForObject(encp, og, use_aes);
1019 1007 if (use_aes) {
1020   - QTC::TC("qpdf", "QPDF_encryption aes decode stream");
1021 1008 decrypt_pipeline =
1022 1009 std::make_unique<Pl_AES_PDF>("AES stream decryption", pipeline, false, key);
1023 1010 } else {
1024   - QTC::TC("qpdf", "QPDF_encryption rc4 decode stream");
1025 1011 decrypt_pipeline = std::make_unique<Pl_RC4>("RC4 stream decryption", pipeline, key);
1026 1012 }
1027 1013 pipeline = decrypt_pipeline.get();
... ...
qpdf/qpdf.testcov
... ... @@ -96,7 +96,6 @@ QPDF recovered stream length 0
96 96 QPDF found wrong endstream in recovery 0
97 97 QPDF_Stream pipeStreamData with null pipeline 0
98 98 QPDFWriter not recompressing /FlateDecode 0
99   -QPDF_encryption xref stream from encrypted file 0
100 99 QPDFJob unable to filter 0
101 100 QUtil non-trivial UTF-16 0
102 101 QPDF xref overwrite invalid objgen 0
... ... @@ -141,16 +140,12 @@ qpdf-c called qpdf_set_minimum_pdf_version 0
141 140 qpdf-c called qpdf_force_pdf_version 0
142 141 qpdf-c called qpdf_init_write multiple times 0
143 142 QPDF_encryption rc4 decode string 0
144   -QPDF_encryption rc4 decode stream 0
145 143 QPDFWriter not compressing metadata 0
146 144 QPDF_encryption aes decode string 0
147   -QPDF_encryption cleartext metadata 0
148   -QPDF_encryption aes decode stream 0
149 145 QPDFWriter forcing object stream disable 0
150 146 QPDFWriter forced version disabled encryption 0
151 147 qpdf-c called qpdf_set_r4_encryption_parameters_insecure 0
152 148 qpdf-c called qpdf_set_static_aes_IV 0
153   -QPDF_encryption stream crypt filter 0
154 149 QPDF ERR object stream with wrong type 0
155 150 QPDF object gone after xref reconstruction 0
156 151 qpdf-c called qpdf_has_error 0
... ...