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

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

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

Powered by Google App Engine
This is Rietveld 408576698