• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The PDFium Authors
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_indirect_object_holder.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 
13 #include "core/fpdfapi/parser/cpdf_object.h"
14 #include "core/fpdfapi/parser/cpdf_parser.h"
15 #include "third_party/base/check.h"
16 
17 namespace {
18 
FilterInvalidObjNum(const CPDF_Object * obj)19 const CPDF_Object* FilterInvalidObjNum(const CPDF_Object* obj) {
20   return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr;
21 }
22 
23 }  // namespace
24 
CPDF_IndirectObjectHolder()25 CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder()
26     : m_pByteStringPool(std::make_unique<ByteStringPool>()) {}
27 
~CPDF_IndirectObjectHolder()28 CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
29   m_pByteStringPool.DeleteObject();  // Make weak.
30 }
31 
GetIndirectObject(uint32_t objnum) const32 RetainPtr<const CPDF_Object> CPDF_IndirectObjectHolder::GetIndirectObject(
33     uint32_t objnum) const {
34   return pdfium::WrapRetain(GetIndirectObjectInternal(objnum));
35 }
36 
GetMutableIndirectObject(uint32_t objnum)37 RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetMutableIndirectObject(
38     uint32_t objnum) {
39   return pdfium::WrapRetain(
40       const_cast<CPDF_Object*>(GetIndirectObjectInternal(objnum)));
41 }
42 
GetIndirectObjectInternal(uint32_t objnum) const43 const CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObjectInternal(
44     uint32_t objnum) const {
45   auto it = m_IndirectObjs.find(objnum);
46   if (it == m_IndirectObjs.end())
47     return nullptr;
48 
49   return FilterInvalidObjNum(it->second.Get());
50 }
51 
GetOrParseIndirectObject(uint32_t objnum)52 RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetOrParseIndirectObject(
53     uint32_t objnum) {
54   return pdfium::WrapRetain(GetOrParseIndirectObjectInternal(objnum));
55 }
56 
GetOrParseIndirectObjectInternal(uint32_t objnum)57 CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObjectInternal(
58     uint32_t objnum) {
59   if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum)
60     return nullptr;
61 
62   // Add item anyway to prevent recursively parsing of same object.
63   auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr));
64   if (!insert_result.second) {
65     return const_cast<CPDF_Object*>(
66         FilterInvalidObjNum(insert_result.first->second.Get()));
67   }
68   RetainPtr<CPDF_Object> pNewObj = ParseIndirectObject(objnum);
69   if (!pNewObj) {
70     m_IndirectObjs.erase(insert_result.first);
71     return nullptr;
72   }
73 
74   pNewObj->SetObjNum(objnum);
75   m_LastObjNum = std::max(m_LastObjNum, objnum);
76 
77   CPDF_Object* result = pNewObj.Get();
78   insert_result.first->second = std::move(pNewObj);
79   return result;
80 }
81 
ParseIndirectObject(uint32_t objnum)82 RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
83     uint32_t objnum) {
84   return nullptr;
85 }
86 
AddIndirectObject(RetainPtr<CPDF_Object> pObj)87 uint32_t CPDF_IndirectObjectHolder::AddIndirectObject(
88     RetainPtr<CPDF_Object> pObj) {
89   CHECK(!pObj->GetObjNum());
90   pObj->SetObjNum(++m_LastObjNum);
91   m_IndirectObjs[m_LastObjNum] = std::move(pObj);
92   return m_LastObjNum;
93 }
94 
ReplaceIndirectObjectIfHigherGeneration(uint32_t objnum,RetainPtr<CPDF_Object> pObj)95 bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration(
96     uint32_t objnum,
97     RetainPtr<CPDF_Object> pObj) {
98   DCHECK(objnum);
99   if (!pObj || objnum == CPDF_Object::kInvalidObjNum)
100     return false;
101 
102   auto& obj_holder = m_IndirectObjs[objnum];
103   const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.Get());
104   if (old_object && pObj->GetGenNum() <= old_object->GetGenNum())
105     return false;
106 
107   pObj->SetObjNum(objnum);
108   obj_holder = std::move(pObj);
109   m_LastObjNum = std::max(m_LastObjNum, objnum);
110   return true;
111 }
112 
DeleteIndirectObject(uint32_t objnum)113 void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) {
114   auto it = m_IndirectObjs.find(objnum);
115   if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.Get()))
116     return;
117 
118   m_IndirectObjs.erase(it);
119 }
120