summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorTom Sepez <tsepez@chromium.org>2018-10-17 17:57:51 +0000
committerChromium commit bot <commit-bot@chromium.org>2018-10-17 17:57:51 +0000
commit5ae6c564d16ce8b625df3d1950abc822f9ecc987 (patch)
tree96bb64df3166e46db397e405789588bf8dc53842 /core
parent785a26dc649af80c593f899a606dff4dae7c48fd (diff)
downloadpdfium-5ae6c564d16ce8b625df3d1950abc822f9ecc987.tar.xz
Add CPDF_{Array,Dictionary}Locker to catch illegal iteration patterns.
Move begin/end methods onto locker object which tracks whether iterators are in existence. Change-Id: Ia869f313fce48d10a0d0180d0cc083eed6ea1584 Reviewed-on: https://pdfium-review.googlesource.com/c/44070 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Tom Sepez <tsepez@chromium.org>
Diffstat (limited to 'core')
-rw-r--r--core/fpdfapi/edit/cpdf_creator.cpp3
-rw-r--r--core/fpdfapi/page/cpdf_allstates.cpp3
-rw-r--r--core/fpdfapi/page/cpdf_colorspace.cpp3
-rw-r--r--core/fpdfapi/page/cpdf_streamcontentparser.cpp51
-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
-rw-r--r--core/fpdfdoc/cpdf_formcontrol.cpp3
-rw-r--r--core/fpdfdoc/cpdf_formfield.cpp3
-rw-r--r--core/fpdfdoc/cpdf_interactiveform.cpp9
18 files changed, 162 insertions, 64 deletions
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp
index c4bc698acc..7eb7673d69 100644
--- a/core/fpdfapi/edit/cpdf_creator.cpp
+++ b/core/fpdfapi/edit/cpdf_creator.cpp
@@ -445,7 +445,8 @@ CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage4() {
if (m_pParser) {
std::unique_ptr<CPDF_Dictionary> p = m_pParser->GetCombinedTrailer();
- for (const auto& it : *p) {
+ CPDF_DictionaryLocker locker(p.get());
+ for (const auto& it : locker) {
const ByteString& key = it.first;
CPDF_Object* pValue = it.second.get();
if (key == "Encrypt" || key == "Size" || key == "Filter" ||
diff --git a/core/fpdfapi/page/cpdf_allstates.cpp b/core/fpdfapi/page/cpdf_allstates.cpp
index 9af904cb5d..3e6692b223 100644
--- a/core/fpdfapi/page/cpdf_allstates.cpp
+++ b/core/fpdfapi/page/cpdf_allstates.cpp
@@ -39,7 +39,8 @@ void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, float phase, float scale) {
void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS,
CPDF_StreamContentParser* pParser) {
- for (const auto& it : *pGS) {
+ CPDF_DictionaryLocker locker(pGS);
+ for (const auto& it : locker) {
const ByteString& key_str = it.first;
CPDF_Object* pElement = it.second.get();
CPDF_Object* pObject = pElement ? pElement->GetDirect() : nullptr;
diff --git a/core/fpdfapi/page/cpdf_colorspace.cpp b/core/fpdfapi/page/cpdf_colorspace.cpp
index 2266dec9e8..bcfd42d72f 100644
--- a/core/fpdfapi/page/cpdf_colorspace.cpp
+++ b/core/fpdfapi/page/cpdf_colorspace.cpp
@@ -461,7 +461,8 @@ std::unique_ptr<CPDF_ColorSpace> CPDF_ColorSpace::Load(
if (!pDict)
return nullptr;
- for (const auto& it : *pDict) {
+ CPDF_DictionaryLocker locker(pDict);
+ for (const auto& it : locker) {
std::unique_ptr<CPDF_ColorSpace> pRet;
CPDF_Object* pValue = it.second.get();
if (ToName(pValue))
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
index 79fa3d2890..beba208739 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
@@ -174,36 +174,39 @@ ByteStringView FindFullName(const AbbrPair* table,
void ReplaceAbbr(CPDF_Object* pObj) {
switch (pObj->GetType()) {
case CPDF_Object::DICTIONARY: {
- CPDF_Dictionary* pDict = pObj->AsDictionary();
std::vector<AbbrReplacementOp> replacements;
- for (const auto& it : *pDict) {
- ByteString key = it.first;
- CPDF_Object* value = it.second.get();
- ByteStringView fullname = FindFullName(
- InlineKeyAbbr, FX_ArraySize(InlineKeyAbbr), key.AsStringView());
- if (!fullname.IsEmpty()) {
- AbbrReplacementOp op;
- op.is_replace_key = true;
- op.key = std::move(key);
- op.replacement = fullname;
- replacements.push_back(op);
- key = fullname;
- }
-
- if (value->IsName()) {
- ByteString name = value->GetString();
- fullname =
- FindFullName(InlineValueAbbr, FX_ArraySize(InlineValueAbbr),
- name.AsStringView());
+ CPDF_Dictionary* pDict = pObj->AsDictionary();
+ {
+ CPDF_DictionaryLocker locker(pDict);
+ for (const auto& it : locker) {
+ ByteString key = it.first;
+ CPDF_Object* value = it.second.get();
+ ByteStringView fullname = FindFullName(
+ InlineKeyAbbr, FX_ArraySize(InlineKeyAbbr), key.AsStringView());
if (!fullname.IsEmpty()) {
AbbrReplacementOp op;
- op.is_replace_key = false;
- op.key = key;
+ op.is_replace_key = true;
+ op.key = std::move(key);
op.replacement = fullname;
replacements.push_back(op);
+ key = fullname;
+ }
+
+ if (value->IsName()) {
+ ByteString name = value->GetString();
+ fullname =
+ FindFullName(InlineValueAbbr, FX_ArraySize(InlineValueAbbr),
+ name.AsStringView());
+ if (!fullname.IsEmpty()) {
+ AbbrReplacementOp op;
+ op.is_replace_key = false;
+ op.key = key;
+ op.replacement = fullname;
+ replacements.push_back(op);
+ }
+ } else {
+ ReplaceAbbr(value);
}
- } else {
- ReplaceAbbr(value);
}
}
for (const auto& op : replacements) {
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);
diff --git a/core/fpdfdoc/cpdf_formcontrol.cpp b/core/fpdfdoc/cpdf_formcontrol.cpp
index edd5fe566c..7ff0914590 100644
--- a/core/fpdfdoc/cpdf_formcontrol.cpp
+++ b/core/fpdfdoc/cpdf_formcontrol.cpp
@@ -48,7 +48,8 @@ ByteString CPDF_FormControl::GetOnStateName() const {
if (!pN)
return csOn;
- for (const auto& it : *pN) {
+ CPDF_DictionaryLocker locker(pN);
+ for (const auto& it : locker) {
if (it.first != "Off")
return it.first;
}
diff --git a/core/fpdfdoc/cpdf_formfield.cpp b/core/fpdfdoc/cpdf_formfield.cpp
index 2b06161b06..89030b4132 100644
--- a/core/fpdfdoc/cpdf_formfield.cpp
+++ b/core/fpdfdoc/cpdf_formfield.cpp
@@ -796,7 +796,8 @@ bool CPDF_FormField::IsOptionSelected(int iOptIndex) const {
if (!pArray)
return false;
- for (const auto& pObj : *pArray) {
+ CPDF_ArrayLocker locker(pArray);
+ for (const auto& pObj : locker) {
if (pObj->GetInteger() == iOptIndex)
return true;
}
diff --git a/core/fpdfdoc/cpdf_interactiveform.cpp b/core/fpdfdoc/cpdf_interactiveform.cpp
index 403344c0ff..382d3dd314 100644
--- a/core/fpdfdoc/cpdf_interactiveform.cpp
+++ b/core/fpdfdoc/cpdf_interactiveform.cpp
@@ -154,7 +154,8 @@ CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict,
if (!pFonts)
return nullptr;
- for (const auto& it : *pFonts) {
+ CPDF_DictionaryLocker locker(pFonts);
+ for (const auto& it : locker) {
const ByteString& csKey = it.first;
if (!it.second)
continue;
@@ -194,7 +195,8 @@ bool FindFont(CPDF_Dictionary* pFormDict,
if (!pFonts)
return false;
- for (const auto& it : *pFonts) {
+ CPDF_DictionaryLocker locker(pFonts);
+ for (const auto& it : locker) {
const ByteString& csKey = it.first;
if (!it.second)
continue;
@@ -230,7 +232,8 @@ bool FindFont(CPDF_Dictionary* pFormDict,
if (csFontName.GetLength() > 0)
csFontName.Remove(' ');
- for (const auto& it : *pFonts) {
+ CPDF_DictionaryLocker locker(pFonts);
+ for (const auto& it : locker) {
const ByteString& csKey = it.first;
if (!it.second)
continue;