summaryrefslogtreecommitdiff
path: root/core/fpdfapi/parser
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/parser')
-rw-r--r--core/fpdfapi/parser/cpdf_array.cpp15
-rw-r--r--core/fpdfapi/parser/cpdf_array.h27
-rw-r--r--core/fpdfapi/parser/cpdf_array_unittest.cpp4
-rw-r--r--core/fpdfapi/parser/cpdf_cross_ref_table.cpp6
-rw-r--r--core/fpdfapi/parser/cpdf_data_avail.cpp3
-rw-r--r--core/fpdfapi/parser/cpdf_dictionary.cpp27
-rw-r--r--core/fpdfapi/parser/cpdf_dictionary.h33
-rw-r--r--core/fpdfapi/parser/cpdf_object.h11
-rw-r--r--core/fpdfapi/parser/cpdf_object_unittest.cpp6
-rw-r--r--core/fpdfapi/parser/cpdf_object_walker.cpp15
-rw-r--r--core/fpdfapi/parser/fpdf_parser_utility.cpp4
11 files changed, 119 insertions, 32 deletions
diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp
index f2eca1be70..e0ac34169f 100644
--- a/core/fpdfapi/parser/cpdf_array.cpp
+++ b/core/fpdfapi/parser/cpdf_array.cpp
@@ -175,16 +175,19 @@ const CPDF_Array* CPDF_Array::GetArrayAt(size_t i) const {
}
void CPDF_Array::Clear() {
+ CHECK(!IsLocked());
m_Objects.clear();
}
void CPDF_Array::RemoveAt(size_t i) {
+ CHECK(!IsLocked());
if (i < m_Objects.size())
m_Objects.erase(m_Objects.begin() + i);
}
void CPDF_Array::ConvertToIndirectObjectAt(size_t i,
CPDF_IndirectObjectHolder* pHolder) {
+ CHECK(!IsLocked());
if (i >= m_Objects.size())
return;
@@ -196,6 +199,7 @@ void CPDF_Array::ConvertToIndirectObjectAt(size_t i,
}
CPDF_Object* CPDF_Array::SetAt(size_t i, std::unique_ptr<CPDF_Object> pObj) {
+ CHECK(!IsLocked());
ASSERT(IsArray());
ASSERT(!pObj || pObj->IsInline());
if (i >= m_Objects.size()) {
@@ -209,6 +213,7 @@ CPDF_Object* CPDF_Array::SetAt(size_t i, std::unique_ptr<CPDF_Object> pObj) {
CPDF_Object* CPDF_Array::InsertAt(size_t index,
std::unique_ptr<CPDF_Object> pObj) {
+ CHECK(!IsLocked());
ASSERT(IsArray());
CHECK(!pObj || pObj->IsInline());
CPDF_Object* pRet = pObj.get();
@@ -224,6 +229,7 @@ CPDF_Object* CPDF_Array::InsertAt(size_t index,
}
CPDF_Object* CPDF_Array::Add(std::unique_ptr<CPDF_Object> pObj) {
+ CHECK(!IsLocked());
ASSERT(IsArray());
CHECK(!pObj || pObj->IsInline());
CPDF_Object* pRet = pObj.get();
@@ -242,3 +248,12 @@ bool CPDF_Array::WriteTo(IFX_ArchiveStream* archive,
}
return archive->WriteString("]");
}
+
+CPDF_ArrayLocker::CPDF_ArrayLocker(const CPDF_Array* pArray)
+ : m_pArray(pArray) {
+ m_pArray->m_LockCount++;
+}
+
+CPDF_ArrayLocker::~CPDF_ArrayLocker() {
+ m_pArray->m_LockCount--;
+}
diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h
index 0905251382..f7b4a1fc9e 100644
--- a/core/fpdfapi/parser/cpdf_array.h
+++ b/core/fpdfapi/parser/cpdf_array.h
@@ -108,17 +108,38 @@ class CPDF_Array final : public CPDF_Object {
void Clear();
void RemoveAt(size_t index);
void ConvertToIndirectObjectAt(size_t index, CPDF_IndirectObjectHolder* pDoc);
-
- const_iterator begin() const { return m_Objects.begin(); }
- const_iterator end() const { return m_Objects.end(); }
+ bool IsLocked() const { return !!m_LockCount; }
private:
+ friend class CPDF_ArrayLocker;
+
std::unique_ptr<CPDF_Object> CloneNonCyclic(
bool bDirect,
std::set<const CPDF_Object*>* pVisited) const override;
std::vector<std::unique_ptr<CPDF_Object>> m_Objects;
WeakPtr<ByteStringPool> m_pPool;
+ mutable uint32_t m_LockCount = 0;
+};
+
+class CPDF_ArrayLocker {
+ public:
+ using const_iterator = CPDF_Array::const_iterator;
+
+ explicit CPDF_ArrayLocker(const CPDF_Array* pArray);
+ ~CPDF_ArrayLocker();
+
+ const_iterator begin() const {
+ CHECK(m_pArray->IsLocked());
+ return m_pArray->m_Objects.begin();
+ }
+ const_iterator end() const {
+ CHECK(m_pArray->IsLocked());
+ return m_pArray->m_Objects.end();
+ }
+
+ private:
+ UnownedPtr<const CPDF_Array> const m_pArray;
};
inline CPDF_Array* ToArray(CPDF_Object* obj) {
diff --git a/core/fpdfapi/parser/cpdf_array_unittest.cpp b/core/fpdfapi/parser/cpdf_array_unittest.cpp
index a70f9910ed..fbc5c393b2 100644
--- a/core/fpdfapi/parser/cpdf_array_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_array_unittest.cpp
@@ -178,7 +178,9 @@ TEST(cpdf_array, Iterator) {
for (size_t i = 0; i < FX_ArraySize(elems); ++i)
arr->InsertNewAt<CPDF_Number>(i, elems[i]);
size_t index = 0;
- for (const auto& it : *arr)
+
+ CPDF_ArrayLocker locker(arr.get());
+ for (const auto& it : locker)
EXPECT_EQ(elems[index++], it->AsNumber()->GetInteger());
EXPECT_EQ(FX_ArraySize(elems), index);
}
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
index 4f7c482c9f..31e9fd3f62 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp
@@ -5,6 +5,7 @@
#include "core/fpdfapi/parser/cpdf_cross_ref_table.h"
#include <utility>
+#include <vector>
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
@@ -153,9 +154,6 @@ void CPDF_CrossRefTable::UpdateTrailer(
new_trailer->SetFor("XRefStm", trailer_->RemoveFor("XRefStm"));
new_trailer->SetFor("Prev", trailer_->RemoveFor("Prev"));
- for (auto it = new_trailer->begin(); it != new_trailer->end();) {
- const ByteString key = it->first;
- ++it;
+ for (const auto& key : new_trailer->GetKeys())
trailer_->SetFor(key, new_trailer->RemoveFor(key));
- }
}
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index c046996498..b685214f6f 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -310,7 +310,8 @@ bool CPDF_DataAvail::CheckPage() {
}
CPDF_Array* pArray = ToArray(pObj.get());
if (pArray) {
- for (const auto& pArrayObj : *pArray) {
+ CPDF_ArrayLocker locker(pArray);
+ for (const auto& pArrayObj : locker) {
if (CPDF_Reference* pRef = ToReference(pArrayObj.get()))
UnavailObjList.push_back(pRef->GetRefObjNum());
}
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index 9c06e42804..6c005c8db2 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -72,7 +72,8 @@ std::unique_ptr<CPDF_Object> CPDF_Dictionary::CloneNonCyclic(
std::set<const CPDF_Object*>* pVisited) const {
pVisited->insert(this);
auto pCopy = pdfium::MakeUnique<CPDF_Dictionary>(m_pPool);
- for (const auto& it : *this) {
+ CPDF_DictionaryLocker locker(this);
+ for (const auto& it : locker) {
if (!pdfium::ContainsKey(*pVisited, it.second.get())) {
std::set<const CPDF_Object*> visited(*pVisited);
if (auto obj = it.second->CloneNonCyclic(bDirect, &visited))
@@ -195,8 +196,17 @@ bool CPDF_Dictionary::KeyExist(const ByteString& key) const {
return pdfium::ContainsKey(m_Map, key);
}
+std::vector<ByteString> CPDF_Dictionary::GetKeys() const {
+ std::vector<ByteString> result;
+ CPDF_DictionaryLocker locker(this);
+ for (const auto& item : locker)
+ result.push_back(item.first);
+ return result;
+}
+
CPDF_Object* CPDF_Dictionary::SetFor(const ByteString& key,
std::unique_ptr<CPDF_Object> pObj) {
+ CHECK(!IsLocked());
if (!pObj) {
m_Map.erase(key);
return nullptr;
@@ -210,6 +220,7 @@ CPDF_Object* CPDF_Dictionary::SetFor(const ByteString& key,
void CPDF_Dictionary::ConvertToIndirectObjectFor(
const ByteString& key,
CPDF_IndirectObjectHolder* pHolder) {
+ CHECK(!IsLocked());
auto it = m_Map.find(key);
if (it == m_Map.end() || it->second->IsReference())
return;
@@ -219,6 +230,7 @@ void CPDF_Dictionary::ConvertToIndirectObjectFor(
}
std::unique_ptr<CPDF_Object> CPDF_Dictionary::RemoveFor(const ByteString& key) {
+ CHECK(!IsLocked());
std::unique_ptr<CPDF_Object> result;
auto it = m_Map.find(key);
if (it != m_Map.end()) {
@@ -230,6 +242,7 @@ std::unique_ptr<CPDF_Object> CPDF_Dictionary::RemoveFor(const ByteString& key) {
void CPDF_Dictionary::ReplaceKey(const ByteString& oldkey,
const ByteString& newkey) {
+ CHECK(!IsLocked());
auto old_it = m_Map.find(oldkey);
if (old_it == m_Map.end())
return;
@@ -273,7 +286,8 @@ bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive,
const bool is_signature = CPDF_CryptoHandler::IsSignatureDictionary(this);
- for (const auto& it : *this) {
+ CPDF_DictionaryLocker locker(this);
+ for (const auto& it : locker) {
const ByteString& key = it.first;
CPDF_Object* pValue = it.second.get();
if (!archive->WriteString("/") ||
@@ -288,3 +302,12 @@ bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive,
}
return archive->WriteString(">>");
}
+
+CPDF_DictionaryLocker::CPDF_DictionaryLocker(const CPDF_Dictionary* pDictionary)
+ : m_pDictionary(pDictionary) {
+ m_pDictionary->m_LockCount++;
+}
+
+CPDF_DictionaryLocker::~CPDF_DictionaryLocker() {
+ m_pDictionary->m_LockCount--;
+}
diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h
index 2e972d0577..e6abd26cc2 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.h
+++ b/core/fpdfapi/parser/cpdf_dictionary.h
@@ -11,12 +11,14 @@
#include <memory>
#include <set>
#include <utility>
+#include <vector>
#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/string_pool_template.h"
#include "core/fxcrt/weak_ptr.h"
+#include "third_party/base/logging.h"
#include "third_party/base/ptr_util.h"
class CPDF_IndirectObjectHolder;
@@ -41,6 +43,8 @@ class CPDF_Dictionary final : public CPDF_Object {
bool WriteTo(IFX_ArchiveStream* archive,
const CPDF_Encryptor* encryptor) const override;
+ bool IsLocked() const { return !!m_LockCount; }
+
size_t size() const { return m_Map.size(); }
const CPDF_Object* GetObjectFor(const ByteString& key) const;
CPDF_Object* GetObjectFor(const ByteString& key);
@@ -65,6 +69,7 @@ class CPDF_Dictionary final : public CPDF_Object {
float GetFloatFor(const ByteString& key) const { return GetNumberFor(key); }
bool KeyExist(const ByteString& key) const;
+ std::vector<ByteString> GetKeys() const;
// Set* functions invalidate iterators for the element with the key |key|.
// Takes ownership of |pObj|, returns an unowned pointer to it.
@@ -76,6 +81,7 @@ class CPDF_Dictionary final : public CPDF_Object {
typename std::enable_if<!CanInternStrings<T>::value, T*>::type SetNewFor(
const ByteString& key,
Args&&... args) {
+ CHECK(!IsLocked());
return static_cast<T*>(
SetFor(key, pdfium::MakeUnique<T>(std::forward<Args>(args)...)));
}
@@ -83,6 +89,7 @@ class CPDF_Dictionary final : public CPDF_Object {
typename std::enable_if<CanInternStrings<T>::value, T*>::type SetNewFor(
const ByteString& key,
Args&&... args) {
+ CHECK(!IsLocked());
return static_cast<T*>(SetFor(
key, pdfium::MakeUnique<T>(m_pPool, std::forward<Args>(args)...)));
}
@@ -100,21 +107,41 @@ class CPDF_Dictionary final : public CPDF_Object {
// Invalidates iterators for the element with the key |oldkey|.
void ReplaceKey(const ByteString& oldkey, const ByteString& newkey);
- const_iterator begin() const { return m_Map.begin(); }
- const_iterator end() const { return m_Map.end(); }
-
WeakPtr<ByteStringPool> GetByteStringPool() const { return m_pPool; }
private:
+ friend class CPDF_DictionaryLocker;
+
ByteString MaybeIntern(const ByteString& str);
std::unique_ptr<CPDF_Object> CloneNonCyclic(
bool bDirect,
std::set<const CPDF_Object*>* visited) const override;
+ mutable uint32_t m_LockCount = 0;
WeakPtr<ByteStringPool> m_pPool;
std::map<ByteString, std::unique_ptr<CPDF_Object>> m_Map;
};
+class CPDF_DictionaryLocker {
+ public:
+ using const_iterator = CPDF_Dictionary::const_iterator;
+
+ explicit CPDF_DictionaryLocker(const CPDF_Dictionary* pDictionary);
+ ~CPDF_DictionaryLocker();
+
+ const_iterator begin() const {
+ CHECK(m_pDictionary->IsLocked());
+ return m_pDictionary->m_Map.begin();
+ }
+ const_iterator end() const {
+ CHECK(m_pDictionary->IsLocked());
+ return m_pDictionary->m_Map.end();
+ }
+
+ private:
+ UnownedPtr<const CPDF_Dictionary> const m_pDictionary;
+};
+
inline CPDF_Dictionary* ToDictionary(CPDF_Object* obj) {
return obj ? obj->AsDictionary() : nullptr;
}
diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h
index 6c6b583963..4f64aec265 100644
--- a/core/fpdfapi/parser/cpdf_object.h
+++ b/core/fpdfapi/parser/cpdf_object.h
@@ -115,16 +115,13 @@ class CPDF_Object {
CPDF_IndirectObjectHolder* holder) const;
protected:
- CPDF_Object() : m_ObjNum(0), m_GenNum(0) {}
+ CPDF_Object() = default;
+ CPDF_Object(const CPDF_Object& src) = delete;
std::unique_ptr<CPDF_Object> CloneObjectNonCyclic(bool bDirect) const;
- uint32_t m_ObjNum;
-
- private:
- CPDF_Object(const CPDF_Object& src) {}
-
- uint32_t m_GenNum;
+ uint32_t m_ObjNum = 0;
+ uint32_t m_GenNum = 0;
};
template <typename T>
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index e5b322ff42..c3ec3aeddb 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -138,9 +138,9 @@ class PDFObjectsTest : public testing::Test {
const CPDF_Dictionary* dict2 = obj2->AsDictionary();
if (dict1->size() != dict2->size())
return false;
- for (CPDF_Dictionary::const_iterator it = dict1->begin();
- it != dict1->end(); ++it) {
- if (!Equal(it->second.get(), dict2->GetObjectFor(it->first)))
+ CPDF_DictionaryLocker locker1(dict1);
+ for (const auto& item : locker1) {
+ if (!Equal(item.second.get(), dict2->GetObjectFor(item.first)))
return false;
}
return true;
diff --git a/core/fpdfapi/parser/cpdf_object_walker.cpp b/core/fpdfapi/parser/cpdf_object_walker.cpp
index 6d6d489e02..f3e1062d83 100644
--- a/core/fpdfapi/parser/cpdf_object_walker.cpp
+++ b/core/fpdfapi/parser/cpdf_object_walker.cpp
@@ -37,11 +37,11 @@ class StreamIterator final : public CPDF_ObjectWalker::SubobjectIterator {
class DictionaryIterator final : public CPDF_ObjectWalker::SubobjectIterator {
public:
explicit DictionaryIterator(const CPDF_Dictionary* dictionary)
- : SubobjectIterator(dictionary) {}
+ : SubobjectIterator(dictionary), locker_(dictionary) {}
~DictionaryIterator() override {}
bool IsFinished() const override {
- return IsStarted() && dict_iterator_ == object()->GetDict()->end();
+ return IsStarted() && dict_iterator_ == locker_.end();
}
const CPDF_Object* IncrementImpl() override {
@@ -55,24 +55,26 @@ class DictionaryIterator final : public CPDF_ObjectWalker::SubobjectIterator {
void Start() override {
ASSERT(!IsStarted());
- dict_iterator_ = object()->GetDict()->begin();
+ dict_iterator_ = locker_.begin();
}
ByteString dict_key() const { return dict_key_; }
private:
CPDF_Dictionary::const_iterator dict_iterator_;
+ CPDF_DictionaryLocker locker_;
ByteString dict_key_;
};
class ArrayIterator final : public CPDF_ObjectWalker::SubobjectIterator {
public:
- explicit ArrayIterator(const CPDF_Array* array) : SubobjectIterator(array) {}
+ explicit ArrayIterator(const CPDF_Array* array)
+ : SubobjectIterator(array), locker_(array) {}
~ArrayIterator() override {}
bool IsFinished() const override {
- return IsStarted() && arr_iterator_ == object()->AsArray()->end();
+ return IsStarted() && arr_iterator_ == locker_.end();
}
const CPDF_Object* IncrementImpl() override {
@@ -83,10 +85,11 @@ class ArrayIterator final : public CPDF_ObjectWalker::SubobjectIterator {
return result;
}
- void Start() override { arr_iterator_ = object()->AsArray()->begin(); }
+ void Start() override { arr_iterator_ = locker_.begin(); }
public:
CPDF_Array::const_iterator arr_iterator_;
+ CPDF_ArrayLocker locker_;
};
} // namespace
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index 4cd02f009e..e6972984ea 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -192,9 +192,9 @@ std::ostream& operator<<(std::ostream& buf, const CPDF_Object* pObj) {
break;
}
case CPDF_Object::DICTIONARY: {
- const CPDF_Dictionary* p = pObj->AsDictionary();
+ CPDF_DictionaryLocker locker(pObj->AsDictionary());
buf << "<<";
- for (const auto& it : *p) {
+ for (const auto& it : locker) {
const ByteString& key = it.first;
CPDF_Object* pValue = it.second.get();
buf << "/" << PDF_NameEncode(key);