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