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