diff options
author | Tom Sepez <tsepez@chromium.org> | 2018-12-13 09:40:49 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-03-29 09:55:48 +0000 |
commit | 4c53ce998eb7416575bbbdcf075e4872036eacc2 (patch) | |
tree | 9bb864690291bbe172bdd2e8bfa52eaae4fad3fc | |
parent | 195a52f52b31da5529d6bba21960e36952b0ab73 (diff) | |
download | qtwebengine-chromium-4c53ce998eb7416575bbbdcf075e4872036eacc2.tar.gz |
[Backport] CVE-2018-17481
Merge M71: Make public IndirectObjectHolder orphan tracking feature
Original CL at https://pdfium-review.googlesource.com/c/45111
Manual merge to avoid conflicts.
Bug: chromium:901654
Reviewed-on: https://pdfium-review.googlesource.com/c/45330
Change-Id: Ifdad31c5ef15b5d2479c571d43b00bd3edbca5e3
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
6 files changed, 45 insertions, 20 deletions
diff --git a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.cpp b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.cpp index 3621dbc1b73..30c330dd78e 100644 --- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.cpp +++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.cpp @@ -204,13 +204,14 @@ void CPDF_Dictionary::ConvertToIndirectObjectFor( it->second = new CPDF_Reference(pHolder, pObj->GetObjNum()); } -void CPDF_Dictionary::RemoveFor(const CFX_ByteString& key) { +std::unique_ptr<CPDF_Object> CPDF_Dictionary::RemoveFor(const CFX_ByteString& key) { + std::unique_ptr<CPDF_Object> result; auto it = m_Map.find(key); - if (it == m_Map.end()) - return; - - delete it->second; - m_Map.erase(it); + if (it != m_Map.end()) { + result = std::unique_ptr<CPDF_Object>(it->second); + m_Map.erase(it); + } + return result; } void CPDF_Dictionary::ReplaceKey(const CFX_ByteString& oldkey, diff --git a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.h b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.h index ebfd7e92eea..1c07a2bec55 100644 --- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.h +++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_dictionary.h @@ -80,7 +80,7 @@ class CPDF_Dictionary : public CPDF_Object { CPDF_IndirectObjectHolder* pHolder); // Invalidates iterators for the element with the key |key|. - void RemoveFor(const CFX_ByteString& key); + std::unique_ptr<CPDF_Object> RemoveFor(const CFX_ByteString& key); // Invalidates iterators for the element with the key |oldkey|. void ReplaceKey(const CFX_ByteString& oldkey, const CFX_ByteString& newkey); diff --git a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp index d1183ebaf47..22dd1ada7df 100644 --- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp +++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.cpp @@ -52,7 +52,8 @@ CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject( CHECK(!pObj->m_ObjNum); CPDF_Object* pUnowned = pObj.get(); pObj->m_ObjNum = ++m_LastObjNum; - m_IndirectObjs[m_LastObjNum].release(); // TODO(tsepez): stop this leak. + AddOrphan(std::move(m_IndirectObjs[m_LastObjNum])); + m_IndirectObjs[m_LastObjNum] = std::move(pObj); return pUnowned; } @@ -69,6 +70,7 @@ bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration( return false; pObj->m_ObjNum = objnum; + AddOrphan(std::move(m_IndirectObjs[objnum])); m_IndirectObjs[objnum] = std::move(pObj); m_LastObjNum = std::max(m_LastObjNum, objnum); return true; @@ -81,3 +83,9 @@ void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) { m_IndirectObjs.erase(objnum); } + +void CPDF_IndirectObjectHolder::AddOrphan( + std::unique_ptr<CPDF_Object> pObject) { + if (pObject) + m_OrphanObjs.push_back(std::move(pObject)); +} diff --git a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.h b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.h index a78e6663b37..87cf3d18d48 100644 --- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.h +++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_indirect_object_holder.h @@ -10,6 +10,7 @@ #include <map> #include <memory> #include <type_traits> +#include <vector> #include "core/fpdfapi/parser/cpdf_object.h" #include "core/fxcrt/cfx_string_pool_template.h" @@ -52,6 +53,11 @@ class CPDF_IndirectObjectHolder { uint32_t objnum, std::unique_ptr<CPDF_Object> pObj); + // Takes ownership of |pObj|, persist it for life of the indirect object + // holder (typically so that unowned pointers to it remain valid). No-op + // if |pObj| is NULL. + void AddOrphan(std::unique_ptr<CPDF_Object> pObj); + uint32_t GetLastObjNum() const { return m_LastObjNum; } void SetLastObjNum(uint32_t objnum) { m_LastObjNum = objnum; } @@ -68,6 +74,7 @@ class CPDF_IndirectObjectHolder { private: uint32_t m_LastObjNum; std::map<uint32_t, std::unique_ptr<CPDF_Object>> m_IndirectObjs; + std::vector<std::unique_ptr<CPDF_Object>> m_OrphanObjs; CFX_WeakPtr<CFX_ByteStringPool> m_pByteStringPool; }; diff --git a/chromium/third_party/pdfium/core/fpdfdoc/cpdf_formfield.cpp b/chromium/third_party/pdfium/core/fpdfdoc/cpdf_formfield.cpp index 3a2213f1aee..44c276924bd 100644 --- a/chromium/third_party/pdfium/core/fpdfdoc/cpdf_formfield.cpp +++ b/chromium/third_party/pdfium/core/fpdfdoc/cpdf_formfield.cpp @@ -223,14 +223,16 @@ bool CPDF_FormField::ResetField(bool bNotify) { if (!pClone) return false; + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("V")); m_pDict->SetFor("V", pClone.release()); if (pRV) { std::unique_ptr<CPDF_Object> pCloneR = pDV->Clone(); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("RV")); m_pDict->SetFor("RV", pCloneR.release()); } } else { - m_pDict->RemoveFor("V"); - m_pDict->RemoveFor("RV"); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("V")); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("RV")); } if (bNotify) NotifyAfterValueChange(); @@ -361,15 +363,18 @@ bool CPDF_FormField::SetValue(const CFX_WideString& value, if (bNotify && !NotifyBeforeValueChange(csValue)) return false; + CFX_ByteString key(bDefault ? "DV" : "V"); int iIndex = FindOptionValue(csValue); if (iIndex < 0) { CFX_ByteString bsEncodeText = PDF_EncodeText(csValue); - m_pDict->SetStringFor(bDefault ? "DV" : "V", bsEncodeText); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor(key)); + m_pDict->SetStringFor(key, bsEncodeText); if (m_Type == RichText && !bDefault) m_pDict->SetStringFor("RV", bsEncodeText); - m_pDict->RemoveFor("I"); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("I")); } else { - m_pDict->SetStringFor(bDefault ? "DV" : "V", PDF_EncodeText(csValue)); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor(key)); + m_pDict->SetStringFor(key, PDF_EncodeText(csValue)); if (!bDefault) { ClearSelection(); SetItemSelection(iIndex, true); @@ -486,8 +491,8 @@ bool CPDF_FormField::ClearSelection(bool bNotify) { if (!NotifyListOrComboBoxBeforeChange(csValue)) return false; } - m_pDict->RemoveFor("V"); - m_pDict->RemoveFor("I"); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("V")); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("I")); if (bNotify) NotifyListOrComboBoxAfterChange(); return true; @@ -573,7 +578,7 @@ bool CPDF_FormField::SetItemSelection(int index, bool bSelected, bool bNotify) { SelectOption(index, false); if (pValue->IsString()) { if (pValue->GetUnicodeText() == opt_value) - m_pDict->RemoveFor("V"); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("V")); } else if (pValue->IsArray()) { std::unique_ptr<CPDF_Array> pArray(new CPDF_Array); for (int i = 0; i < CountOptions(); i++) { @@ -582,12 +587,14 @@ bool CPDF_FormField::SetItemSelection(int index, bool bSelected, bool bNotify) { pArray->AddNew<CPDF_String>(PDF_EncodeText(opt_value), false); } } - if (pArray->GetCount() > 0) + if (pArray->GetCount() > 0) { + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("V")); m_pDict->SetFor("V", pArray.release()); // std::move someday + } } } else { - m_pDict->RemoveFor("V"); - m_pDict->RemoveFor("I"); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("V")); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("I")); } } } @@ -888,7 +895,7 @@ bool CPDF_FormField::SelectOption(int iOptIndex, bool bSelected, bool bNotify) { pArray->AddNew<CPDF_Number>(iOptIndex); if (pArray->IsEmpty()) - m_pDict->RemoveFor("I"); + m_pForm->GetDocument()->AddOrphan(m_pDict->RemoveFor("I")); } if (bNotify) NotifyListOrComboBoxAfterChange(); diff --git a/chromium/third_party/pdfium/core/fpdfdoc/cpdf_interform.h b/chromium/third_party/pdfium/core/fpdfdoc/cpdf_interform.h index fbff0289a1d..99fcb432f0e 100644 --- a/chromium/third_party/pdfium/core/fpdfdoc/cpdf_interform.h +++ b/chromium/third_party/pdfium/core/fpdfdoc/cpdf_interform.h @@ -89,6 +89,8 @@ class CPDF_InterForm { bool HasXFAForm() const; void FixPageFields(const CPDF_Page* pPage); + CPDF_Document* GetDocument() const { return m_pDocument; } + private: friend class CPDF_FormControl; friend class CPDF_FormField; |