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 1028 qpdf_offset_t read_xrefTable(qpdf_offset_t offset);
1029 1029 qpdf_offset_t read_xrefStream(qpdf_offset_t offset);
1030 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 1033 std::pair<size_t, std::vector<long long>> processXRefIndex(
1032 1034 QPDFObjectHandle& dict,
1033 1035 size_t entry_size,
... ...
libqpdf/QPDF.cc
... ... @@ -968,6 +968,36 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset)
968 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 1001 // Return the expected size of the xref stream and the processed Index array.
972 1002 std::pair<size_t, std::vector<long long>>
973 1003 QPDF::processXRefIndex(
... ... @@ -1033,28 +1063,12 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1033 1063 };
1034 1064  
1035 1065 auto dict = xref_obj.getDict();
1036   - auto W_obj = dict.getKey("/W");
1037 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 1072 auto [expected_size, indx] = processXRefIndex(dict, entry_size, damaged);
1059 1073  
1060 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 1104 throw std::range_error(msg.str());
1091 1105 }
1092 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 1109 fields[j] = 0;
1096 1110 if ((j == 0) && (W[0] == 0)) {
1097 1111 QTC::TC("qpdf", "QPDF default for xref stream field 0");
... ...