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/parser/cpdf_linearized_header.h" 8 9 #include <algorithm> 10 #include <utility> 11 12 #include "core/fpdfapi/parser/cpdf_array.h" 13 #include "core/fpdfapi/parser/cpdf_dictionary.h" 14 #include "core/fpdfapi/parser/cpdf_number.h" 15 #include "third_party/base/ptr_util.h" 16 17 namespace { 18 19 template <class T> 20 bool IsValidNumericDictionaryValue(const CPDF_Dictionary* pDict, 21 const char* key, 22 T min_value, 23 bool must_exist = true) { 24 if (!pDict->KeyExist(key)) 25 return !must_exist; 26 const CPDF_Number* pNum = ToNumber(pDict->GetObjectFor(key)); 27 if (!pNum || !pNum->IsInteger()) 28 return false; 29 const int raw_value = pNum->GetInteger(); 30 if (!pdfium::base::IsValueInRangeForNumericType<T>(raw_value)) 31 return false; 32 return static_cast<T>(raw_value) >= min_value; 33 } 34 35 } // namespace 36 37 // static 38 std::unique_ptr<CPDF_LinearizedHeader> CPDF_LinearizedHeader::CreateForObject( 39 std::unique_ptr<CPDF_Object> pObj) { 40 auto pDict = ToDictionary(std::move(pObj)); 41 if (!pDict || !pDict->KeyExist("Linearized") || 42 !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "L", 1) || 43 !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "P", 0, false) || 44 !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "T", 1) || 45 !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "N", 0) || 46 !IsValidNumericDictionaryValue<FX_FILESIZE>(pDict.get(), "E", 1) || 47 !IsValidNumericDictionaryValue<uint32_t>(pDict.get(), "O", 1)) 48 return nullptr; 49 return pdfium::WrapUnique(new CPDF_LinearizedHeader(pDict.get())); 50 } 51 52 CPDF_LinearizedHeader::CPDF_LinearizedHeader(const CPDF_Dictionary* pDict) { 53 m_szFileSize = pDict->GetIntegerFor("L"); 54 m_dwFirstPageNo = pDict->GetIntegerFor("P"); 55 m_szLastXRefOffset = pDict->GetIntegerFor("T"); 56 m_PageCount = pDict->GetIntegerFor("N"); 57 m_szFirstPageEndOffset = pDict->GetIntegerFor("E"); 58 m_FirstPageObjNum = pDict->GetIntegerFor("O"); 59 const CPDF_Array* pHintStreamRange = pDict->GetArrayFor("H"); 60 const size_t nHintStreamSize = 61 pHintStreamRange ? pHintStreamRange->GetCount() : 0; 62 if (nHintStreamSize == 2 || nHintStreamSize == 4) { 63 m_szHintStart = std::max(pHintStreamRange->GetIntegerAt(0), 0); 64 m_szHintLength = std::max(pHintStreamRange->GetIntegerAt(1), 0); 65 } 66 } 67 68 CPDF_LinearizedHeader::~CPDF_LinearizedHeader() {} 69 70 bool CPDF_LinearizedHeader::HasHintTable() const { 71 return GetPageCount() > 1 && GetHintStart() > 0 && GetHintLength() > 0; 72 } 73