Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: core/src/fpdfapi/fpdf_parser/cpdf_hint_tables.cpp

Issue 1800523005: Move core/src/ up to core/. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/src/fpdfapi/fpdf_parser/cpdf_hint_tables.h"
8
9 #include "core/include/fxcrt/fx_safe_types.h"
10 #include "core/include/fpdfapi/cpdf_array.h"
11 #include "core/include/fpdfapi/cpdf_dictionary.h"
12 #include "core/include/fpdfapi/cpdf_stream.h"
13 #include "core/src/fpdfapi/fpdf_parser/cpdf_data_avail.h"
14
15 namespace {
16
17 bool CanReadFromBitStream(const CFX_BitStream* hStream,
18 const FX_SAFE_DWORD& num_bits) {
19 return num_bits.IsValid() &&
20 hStream->BitsRemaining() >= num_bits.ValueOrDie();
21 }
22
23 } // namespace
24
25 CPDF_HintTables::~CPDF_HintTables() {
26 m_dwDeltaNObjsArray.RemoveAll();
27 m_dwNSharedObjsArray.RemoveAll();
28 m_dwSharedObjNumArray.RemoveAll();
29 m_dwIdentifierArray.RemoveAll();
30 }
31
32 FX_DWORD CPDF_HintTables::GetItemLength(
33 int index,
34 const std::vector<FX_FILESIZE>& szArray) {
35 if (index < 0 || szArray.size() < 2 ||
36 static_cast<size_t>(index) > szArray.size() - 2 ||
37 szArray[index] > szArray[index + 1]) {
38 return 0;
39 }
40 return szArray[index + 1] - szArray[index];
41 }
42
43 FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
44 if (!hStream || hStream->IsEOF())
45 return FALSE;
46
47 int nStreamOffset = ReadPrimaryHintStreamOffset();
48 int nStreamLen = ReadPrimaryHintStreamLength();
49 if (nStreamOffset < 0 || nStreamLen < 1)
50 return FALSE;
51
52 const FX_DWORD kHeaderSize = 288;
53 if (hStream->BitsRemaining() < kHeaderSize)
54 return FALSE;
55
56 // Item 1: The least number of objects in a page.
57 FX_DWORD dwObjLeastNum = hStream->GetBits(32);
58
59 // Item 2: The location of the first page's page object.
60 FX_DWORD dwFirstObjLoc = hStream->GetBits(32);
61 if (dwFirstObjLoc > nStreamOffset) {
62 FX_SAFE_DWORD safeLoc = pdfium::base::checked_cast<FX_DWORD>(nStreamLen);
63 safeLoc += dwFirstObjLoc;
64 if (!safeLoc.IsValid())
65 return FALSE;
66 m_szFirstPageObjOffset =
67 pdfium::base::checked_cast<FX_FILESIZE>(safeLoc.ValueOrDie());
68 } else {
69 m_szFirstPageObjOffset =
70 pdfium::base::checked_cast<FX_FILESIZE>(dwFirstObjLoc);
71 }
72
73 // Item 3: The number of bits needed to represent the difference
74 // between the greatest and least number of objects in a page.
75 FX_DWORD dwDeltaObjectsBits = hStream->GetBits(16);
76
77 // Item 4: The least length of a page in bytes.
78 FX_DWORD dwPageLeastLen = hStream->GetBits(32);
79
80 // Item 5: The number of bits needed to represent the difference
81 // between the greatest and least length of a page, in bytes.
82 FX_DWORD dwDeltaPageLenBits = hStream->GetBits(16);
83
84 // Skip Item 6, 7, 8, 9 total 96 bits.
85 hStream->SkipBits(96);
86
87 // Item 10: The number of bits needed to represent the greatest
88 // number of shared object references.
89 FX_DWORD dwSharedObjBits = hStream->GetBits(16);
90
91 // Item 11: The number of bits needed to represent the numerically
92 // greatest shared object identifier used by the pages.
93 FX_DWORD dwSharedIdBits = hStream->GetBits(16);
94
95 // Item 12: The number of bits needed to represent the numerator of
96 // the fractional position for each shared object reference. For each
97 // shared object referenced from a page, there is an indication of
98 // where in the page's content stream the object is first referenced.
99 FX_DWORD dwSharedNumeratorBits = hStream->GetBits(16);
100
101 // Item 13: Skip Item 13 which has 16 bits.
102 hStream->SkipBits(16);
103
104 CPDF_Object* pPageNum = m_pLinearizedDict->GetElementValue("N");
105 int nPages = pPageNum ? pPageNum->GetInteger() : 0;
106 if (nPages < 1)
107 return FALSE;
108
109 FX_SAFE_DWORD required_bits = dwDeltaObjectsBits;
110 required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
111 if (!CanReadFromBitStream(hStream, required_bits))
112 return FALSE;
113
114 for (int i = 0; i < nPages; ++i) {
115 FX_SAFE_DWORD safeDeltaObj = hStream->GetBits(dwDeltaObjectsBits);
116 safeDeltaObj += dwObjLeastNum;
117 if (!safeDeltaObj.IsValid())
118 return FALSE;
119 m_dwDeltaNObjsArray.Add(safeDeltaObj.ValueOrDie());
120 }
121 hStream->ByteAlign();
122
123 required_bits = dwDeltaPageLenBits;
124 required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
125 if (!CanReadFromBitStream(hStream, required_bits))
126 return FALSE;
127
128 CFX_DWordArray dwPageLenArray;
129 for (int i = 0; i < nPages; ++i) {
130 FX_SAFE_DWORD safePageLen = hStream->GetBits(dwDeltaPageLenBits);
131 safePageLen += dwPageLeastLen;
132 if (!safePageLen.IsValid())
133 return FALSE;
134 dwPageLenArray.Add(safePageLen.ValueOrDie());
135 }
136
137 CPDF_Object* pOffsetE = m_pLinearizedDict->GetElementValue("E");
138 int nOffsetE = pOffsetE ? pOffsetE->GetInteger() : -1;
139 if (nOffsetE < 0)
140 return FALSE;
141
142 CPDF_Object* pFirstPageNum = m_pLinearizedDict->GetElementValue("P");
143 int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
144 for (int i = 0; i < nPages; ++i) {
145 if (i == nFirstPageNum) {
146 m_szPageOffsetArray.push_back(m_szFirstPageObjOffset);
147 } else if (i == nFirstPageNum + 1) {
148 if (i == 1) {
149 m_szPageOffsetArray.push_back(nOffsetE);
150 } else {
151 m_szPageOffsetArray.push_back(m_szPageOffsetArray[i - 2] +
152 dwPageLenArray[i - 2]);
153 }
154 } else {
155 if (i == 0) {
156 m_szPageOffsetArray.push_back(nOffsetE);
157 } else {
158 m_szPageOffsetArray.push_back(m_szPageOffsetArray[i - 1] +
159 dwPageLenArray[i - 1]);
160 }
161 }
162 }
163
164 if (nPages > 0) {
165 m_szPageOffsetArray.push_back(m_szPageOffsetArray[nPages - 1] +
166 dwPageLenArray[nPages - 1]);
167 }
168 hStream->ByteAlign();
169
170 // Number of shared objects.
171 required_bits = dwSharedObjBits;
172 required_bits *= pdfium::base::checked_cast<FX_DWORD>(nPages);
173 if (!CanReadFromBitStream(hStream, required_bits))
174 return FALSE;
175
176 for (int i = 0; i < nPages; i++)
177 m_dwNSharedObjsArray.Add(hStream->GetBits(dwSharedObjBits));
178 hStream->ByteAlign();
179
180 // Array of identifiers, size = nshared_objects.
181 for (int i = 0; i < nPages; i++) {
182 required_bits = dwSharedIdBits;
183 required_bits *= m_dwNSharedObjsArray[i];
184 if (!CanReadFromBitStream(hStream, required_bits))
185 return FALSE;
186
187 for (int j = 0; j < m_dwNSharedObjsArray[i]; j++)
188 m_dwIdentifierArray.Add(hStream->GetBits(dwSharedIdBits));
189 }
190 hStream->ByteAlign();
191
192 for (int i = 0; i < nPages; i++) {
193 FX_SAFE_DWORD safeSize = m_dwNSharedObjsArray[i];
194 safeSize *= dwSharedNumeratorBits;
195 if (!CanReadFromBitStream(hStream, safeSize))
196 return FALSE;
197
198 hStream->SkipBits(safeSize.ValueOrDie());
199 }
200 hStream->ByteAlign();
201
202 FX_SAFE_DWORD safeTotalPageLen = pdfium::base::checked_cast<FX_DWORD>(nPages);
203 safeTotalPageLen *= dwDeltaPageLenBits;
204 if (!CanReadFromBitStream(hStream, safeTotalPageLen))
205 return FALSE;
206
207 hStream->SkipBits(safeTotalPageLen.ValueOrDie());
208 hStream->ByteAlign();
209 return TRUE;
210 }
211
212 FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream,
213 FX_DWORD offset) {
214 if (!hStream || hStream->IsEOF())
215 return FALSE;
216
217 int nStreamOffset = ReadPrimaryHintStreamOffset();
218 int nStreamLen = ReadPrimaryHintStreamLength();
219 if (nStreamOffset < 0 || nStreamLen < 1)
220 return FALSE;
221
222 FX_SAFE_DWORD bit_offset = offset;
223 bit_offset *= 8;
224 if (!bit_offset.IsValid() || hStream->GetPos() > bit_offset.ValueOrDie())
225 return FALSE;
226 hStream->SkipBits(bit_offset.ValueOrDie() - hStream->GetPos());
227
228 const FX_DWORD kHeaderSize = 192;
229 if (hStream->BitsRemaining() < kHeaderSize)
230 return FALSE;
231
232 // Item 1: The object number of the first object in the shared objects
233 // section.
234 FX_DWORD dwFirstSharedObjNum = hStream->GetBits(32);
235
236 // Item 2: The location of the first object in the shared objects section.
237 FX_DWORD dwFirstSharedObjLoc = hStream->GetBits(32);
238 if (dwFirstSharedObjLoc > nStreamOffset)
239 dwFirstSharedObjLoc += nStreamLen;
240
241 // Item 3: The number of shared object entries for the first page.
242 m_nFirstPageSharedObjs = hStream->GetBits(32);
243
244 // Item 4: The number of shared object entries for the shared objects
245 // section, including the number of shared object entries for the first page.
246 FX_DWORD dwSharedObjTotal = hStream->GetBits(32);
247
248 // Item 5: The number of bits needed to represent the greatest number of
249 // objects in a shared object group. Skipped.
250 hStream->SkipBits(16);
251
252 // Item 6: The least length of a shared object group in bytes.
253 FX_DWORD dwGroupLeastLen = hStream->GetBits(32);
254
255 // Item 7: The number of bits needed to represent the difference between the
256 // greatest and least length of a shared object group, in bytes.
257 FX_DWORD dwDeltaGroupLen = hStream->GetBits(16);
258 CPDF_Object* pFirstPageObj = m_pLinearizedDict->GetElementValue("O");
259 int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
260 if (nFirstPageObjNum < 0)
261 return FALSE;
262
263 FX_DWORD dwPrevObjLen = 0;
264 FX_DWORD dwCurObjLen = 0;
265 FX_SAFE_DWORD required_bits = dwSharedObjTotal;
266 required_bits *= dwDeltaGroupLen;
267 if (!CanReadFromBitStream(hStream, required_bits))
268 return FALSE;
269
270 for (FX_DWORD i = 0; i < dwSharedObjTotal; ++i) {
271 dwPrevObjLen = dwCurObjLen;
272 FX_SAFE_DWORD safeObjLen = hStream->GetBits(dwDeltaGroupLen);
273 safeObjLen += dwGroupLeastLen;
274 if (!safeObjLen.IsValid())
275 return FALSE;
276
277 dwCurObjLen = safeObjLen.ValueOrDie();
278 if (i < m_nFirstPageSharedObjs) {
279 m_dwSharedObjNumArray.Add(nFirstPageObjNum + i);
280 if (i == 0)
281 m_szSharedObjOffsetArray.push_back(m_szFirstPageObjOffset);
282 } else {
283 FX_SAFE_DWORD safeObjNum = dwFirstSharedObjNum;
284 safeObjNum += i - m_nFirstPageSharedObjs;
285 if (!safeObjNum.IsValid())
286 return FALSE;
287
288 m_dwSharedObjNumArray.Add(safeObjNum.ValueOrDie());
289 if (i == m_nFirstPageSharedObjs) {
290 m_szSharedObjOffsetArray.push_back(
291 pdfium::base::checked_cast<int32_t>(dwFirstSharedObjLoc));
292 }
293 }
294
295 if (i != 0 && i != m_nFirstPageSharedObjs) {
296 FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwPrevObjLen);
297 safeLoc += m_szSharedObjOffsetArray[i - 1];
298 if (!safeLoc.IsValid())
299 return FALSE;
300
301 m_szSharedObjOffsetArray.push_back(safeLoc.ValueOrDie());
302 }
303 }
304
305 if (dwSharedObjTotal > 0) {
306 FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwCurObjLen);
307 safeLoc += m_szSharedObjOffsetArray[dwSharedObjTotal - 1];
308 if (!safeLoc.IsValid())
309 return FALSE;
310
311 m_szSharedObjOffsetArray.push_back(safeLoc.ValueOrDie());
312 }
313
314 hStream->ByteAlign();
315 if (hStream->BitsRemaining() < dwSharedObjTotal)
316 return FALSE;
317
318 hStream->SkipBits(dwSharedObjTotal);
319 hStream->ByteAlign();
320 return TRUE;
321 }
322
323 FX_BOOL CPDF_HintTables::GetPagePos(int index,
324 FX_FILESIZE& szPageStartPos,
325 FX_FILESIZE& szPageLength,
326 FX_DWORD& dwObjNum) {
327 if (!m_pLinearizedDict)
328 return FALSE;
329
330 szPageStartPos = m_szPageOffsetArray[index];
331 szPageLength = GetItemLength(index, m_szPageOffsetArray);
332
333 CPDF_Object* pFirstPageNum = m_pLinearizedDict->GetElementValue("P");
334 int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
335
336 CPDF_Object* pFirstPageObjNum = m_pLinearizedDict->GetElementValue("O");
337 if (!pFirstPageObjNum)
338 return FALSE;
339
340 int nFirstPageObjNum = pFirstPageObjNum->GetInteger();
341 if (index == nFirstPageNum) {
342 dwObjNum = nFirstPageObjNum;
343 return TRUE;
344 }
345
346 // The object number of remaining pages starts from 1.
347 dwObjNum = 1;
348 for (int i = 0; i < index; ++i) {
349 if (i == nFirstPageNum)
350 continue;
351 dwObjNum += m_dwDeltaNObjsArray[i];
352 }
353 return TRUE;
354 }
355
356 IPDF_DataAvail::DocAvailStatus CPDF_HintTables::CheckPage(
357 int index,
358 IPDF_DataAvail::DownloadHints* pHints) {
359 if (!m_pLinearizedDict || !pHints)
360 return IPDF_DataAvail::DataError;
361
362 CPDF_Object* pFirstAvailPage = m_pLinearizedDict->GetElementValue("P");
363 int nFirstAvailPage = pFirstAvailPage ? pFirstAvailPage->GetInteger() : 0;
364 if (index == nFirstAvailPage)
365 return IPDF_DataAvail::DataAvailable;
366
367 FX_DWORD dwLength = GetItemLength(index, m_szPageOffsetArray);
368 // If two pages have the same offset, it should be treated as an error.
369 if (!dwLength)
370 return IPDF_DataAvail::DataError;
371
372 if (!m_pDataAvail->IsDataAvail(m_szPageOffsetArray[index], dwLength, pHints))
373 return IPDF_DataAvail::DataNotAvailable;
374
375 // Download data of shared objects in the page.
376 FX_DWORD offset = 0;
377 for (int i = 0; i < index; ++i)
378 offset += m_dwNSharedObjsArray[i];
379
380 CPDF_Object* pFirstPageObj = m_pLinearizedDict->GetElementValue("O");
381 int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
382 if (nFirstPageObjNum < 0)
383 return IPDF_DataAvail::DataError;
384
385 FX_DWORD dwIndex = 0;
386 FX_DWORD dwObjNum = 0;
387 for (int j = 0; j < m_dwNSharedObjsArray[index]; ++j) {
388 dwIndex = m_dwIdentifierArray[offset + j];
389 if (dwIndex >= m_dwSharedObjNumArray.GetSize())
390 return IPDF_DataAvail::DataNotAvailable;
391
392 dwObjNum = m_dwSharedObjNumArray[dwIndex];
393 if (dwObjNum >= nFirstPageObjNum &&
394 dwObjNum < nFirstPageObjNum + m_nFirstPageSharedObjs) {
395 continue;
396 }
397
398 dwLength = GetItemLength(dwIndex, m_szSharedObjOffsetArray);
399 // If two objects have the same offset, it should be treated as an error.
400 if (!dwLength)
401 return IPDF_DataAvail::DataError;
402
403 if (!m_pDataAvail->IsDataAvail(m_szSharedObjOffsetArray[dwIndex], dwLength,
404 pHints)) {
405 return IPDF_DataAvail::DataNotAvailable;
406 }
407 }
408 return IPDF_DataAvail::DataAvailable;
409 }
410
411 FX_BOOL CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) {
412 if (!pHintStream || !m_pLinearizedDict)
413 return FALSE;
414
415 CPDF_Dictionary* pDict = pHintStream->GetDict();
416 CPDF_Object* pOffset = pDict ? pDict->GetElement("S") : nullptr;
417 if (!pOffset || !pOffset->IsNumber())
418 return FALSE;
419
420 int shared_hint_table_offset = pOffset->GetInteger();
421 CPDF_StreamAcc acc;
422 acc.LoadAllData(pHintStream);
423
424 FX_DWORD size = acc.GetSize();
425 // The header section of page offset hint table is 36 bytes.
426 // The header section of shared object hint table is 24 bytes.
427 // Hint table has at least 60 bytes.
428 const FX_DWORD MIN_STREAM_LEN = 60;
429 if (size < MIN_STREAM_LEN || shared_hint_table_offset <= 0 ||
430 size < shared_hint_table_offset) {
431 return FALSE;
432 }
433
434 CFX_BitStream bs;
435 bs.Init(acc.GetData(), size);
436 return ReadPageHintTable(&bs) &&
437 ReadSharedObjHintTable(&bs, pdfium::base::checked_cast<FX_DWORD>(
438 shared_hint_table_offset));
439 }
440
441 int CPDF_HintTables::ReadPrimaryHintStreamOffset() const {
442 if (!m_pLinearizedDict)
443 return -1;
444
445 CPDF_Array* pRange = m_pLinearizedDict->GetArrayBy("H");
446 if (!pRange)
447 return -1;
448
449 CPDF_Object* pStreamOffset = pRange->GetElementValue(0);
450 if (!pStreamOffset)
451 return -1;
452
453 return pStreamOffset->GetInteger();
454 }
455
456 int CPDF_HintTables::ReadPrimaryHintStreamLength() const {
457 if (!m_pLinearizedDict)
458 return -1;
459
460 CPDF_Array* pRange = m_pLinearizedDict->GetArrayBy("H");
461 if (!pRange)
462 return -1;
463
464 CPDF_Object* pStreamLen = pRange->GetElementValue(1);
465 if (!pStreamLen)
466 return -1;
467
468 return pStreamLen->GetInteger();
469 }
OLDNEW
« no previous file with comments | « core/src/fpdfapi/fpdf_parser/cpdf_hint_tables.h ('k') | core/src/fpdfapi/fpdf_parser/cpdf_indirect_object_holder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698