Commit f74b28f0d1cf2c6302dedd2c24dac1cc077c77a5

Authored by m-holger
1 parent 0186d60d

Add new private method QPDF::processXRefW

include/qpdf/QPDF.hh
@@ -1028,6 +1028,8 @@ class QPDF @@ -1028,6 +1028,8 @@ class QPDF
1028 qpdf_offset_t read_xrefTable(qpdf_offset_t offset); 1028 qpdf_offset_t read_xrefTable(qpdf_offset_t offset);
1029 qpdf_offset_t read_xrefStream(qpdf_offset_t offset); 1029 qpdf_offset_t read_xrefStream(qpdf_offset_t offset);
1030 qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); 1030 qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
  1031 + std::pair<size_t, std::array<int, 3>>
  1032 + processXRefW(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged);
1031 std::pair<size_t, std::vector<long long>> processXRefIndex( 1033 std::pair<size_t, std::vector<long long>> processXRefIndex(
1032 QPDFObjectHandle& dict, 1034 QPDFObjectHandle& dict,
1033 size_t entry_size, 1035 size_t entry_size,
libqpdf/QPDF.cc
@@ -968,6 +968,36 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset) @@ -968,6 +968,36 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset)
968 return 0; // unreachable 968 return 0; // unreachable
969 } 969 }
970 970
  971 +// Return the entry size of the xref stream and the processed W array.
  972 +std::pair<size_t, std::array<int, 3>>
  973 +QPDF::processXRefW(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged)
  974 +{
  975 + auto W_obj = dict.getKey("/W");
  976 + if (!(W_obj.isArray() && (W_obj.getArrayNItems() >= 3) && W_obj.getArrayItem(0).isInteger() &&
  977 + W_obj.getArrayItem(1).isInteger() && W_obj.getArrayItem(2).isInteger())) {
  978 + throw damaged("Cross-reference stream does not have a proper /W key");
  979 + }
  980 +
  981 + std::array<int, 3> W;
  982 + int entry_size = 0;
  983 + auto w_vector = W_obj.getArrayAsVector();
  984 + int max_bytes = sizeof(qpdf_offset_t);
  985 + for (size_t i = 0; i < 3; ++i) {
  986 + W[i] = w_vector[i].getIntValueAsInt();
  987 + if (W[i] > max_bytes) {
  988 + throw damaged("Cross-reference stream's /W contains impossibly large values");
  989 + }
  990 + if (W[i] < 0) {
  991 + throw damaged("Cross-reference stream's /W contains negative values");
  992 + }
  993 + entry_size += W[i];
  994 + }
  995 + if (entry_size == 0) {
  996 + throw damaged("Cross-reference stream's /W indicates entry size of 0");
  997 + }
  998 + return {toS(entry_size), W};
  999 +}
  1000 +
971 // Return the expected size of the xref stream and the processed Index array. 1001 // Return the expected size of the xref stream and the processed Index array.
972 std::pair<size_t, std::vector<long long>> 1002 std::pair<size_t, std::vector<long long>>
973 QPDF::processXRefIndex( 1003 QPDF::processXRefIndex(
@@ -1033,28 +1063,12 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -1033,28 +1063,12 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1033 }; 1063 };
1034 1064
1035 auto dict = xref_obj.getDict(); 1065 auto dict = xref_obj.getDict();
1036 - auto W_obj = dict.getKey("/W");  
1037 auto Size_obj = dict.getKey("/Size"); 1066 auto Size_obj = dict.getKey("/Size");
1038 - if (!(W_obj.isArray() && (W_obj.getArrayNItems() >= 3) && W_obj.getArrayItem(0).isInteger() &&  
1039 - W_obj.getArrayItem(1).isInteger() && W_obj.getArrayItem(2).isInteger() &&  
1040 - Size_obj.isInteger())) {  
1041 - throw damaged("Cross-reference stream does not have a proper /W key");  
1042 - }  
1043 -  
1044 - int W[3];  
1045 - size_t entry_size = 0;  
1046 - int max_bytes = sizeof(qpdf_offset_t);  
1047 - for (int i = 0; i < 3; ++i) {  
1048 - W[i] = W_obj.getArrayItem(i).getIntValueAsInt();  
1049 - if (W[i] > max_bytes) {  
1050 - throw damaged("Cross-reference stream's /W contains impossibly large values");  
1051 - }  
1052 - entry_size += toS(W[i]);  
1053 - }  
1054 - if (entry_size == 0) {  
1055 - throw damaged("Cross-reference stream's /W indicates entry size of 0"); 1067 + if (!Size_obj.isInteger()) {
  1068 + throw damaged("Cross-reference stream does not have a proper /Size key");
1056 } 1069 }
1057 1070
  1071 + auto [entry_size, W] = processXRefW(dict, damaged);
1058 auto [expected_size, indx] = processXRefIndex(dict, entry_size, damaged); 1072 auto [expected_size, indx] = processXRefIndex(dict, entry_size, damaged);
1059 1073
1060 std::shared_ptr<Buffer> bp = xref_obj.getStreamData(qpdf_dl_specialized); 1074 std::shared_ptr<Buffer> bp = xref_obj.getStreamData(qpdf_dl_specialized);
@@ -1090,8 +1104,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -1090,8 +1104,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1090 throw std::range_error(msg.str()); 1104 throw std::range_error(msg.str());
1091 } 1105 }
1092 // Read this entry 1106 // Read this entry
1093 - qpdf_offset_t fields[3];  
1094 - for (int j = 0; j < 3; ++j) { 1107 + std::array<qpdf_offset_t, 3> fields;
  1108 + for (size_t j = 0; j < 3; ++j) {
1095 fields[j] = 0; 1109 fields[j] = 0;
1096 if ((j == 0) && (W[0] == 0)) { 1110 if ((j == 0) && (W[0] == 0)) {
1097 QTC::TC("qpdf", "QPDF default for xref stream field 0"); 1111 QTC::TC("qpdf", "QPDF default for xref stream field 0");