Commit f74b28f0d1cf2c6302dedd2c24dac1cc077c77a5
1 parent
0186d60d
Add new private method QPDF::processXRefW
Showing
2 changed files
with
37 additions
and
21 deletions
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& 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& 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"); | ... | ... |