diff options
-rw-r--r-- | core/fpdfapi/page/cpdf_contentparser.cpp | 71 | ||||
-rw-r--r-- | core/fpdfapi/page/cpdf_contentparser.h | 6 |
2 files changed, 52 insertions, 25 deletions
diff --git a/core/fpdfapi/page/cpdf_contentparser.cpp b/core/fpdfapi/page/cpdf_contentparser.cpp index 471e707322..29b5f122bd 100644 --- a/core/fpdfapi/page/cpdf_contentparser.cpp +++ b/core/fpdfapi/page/cpdf_contentparser.cpp @@ -16,6 +16,7 @@ #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" +#include "core/fxcrt/fx_safe_types.h" #include "core/fxcrt/pauseindicator_iface.h" #include "third_party/base/ptr_util.h" @@ -37,11 +38,9 @@ CPDF_ContentParser::CPDF_ContentParser(CPDF_Page* pPage) CPDF_Stream* pStream = pContent->AsStream(); if (pStream) { - RetainPtr<CPDF_StreamAcc> pSingleStream = - pdfium::MakeRetain<CPDF_StreamAcc>(pStream); - pSingleStream->LoadAllDataFiltered(); - m_StreamArray.push_back(pSingleStream); - m_CurrentStage = Stage::kParse; + m_pSingleStream = pdfium::MakeRetain<CPDF_StreamAcc>(pStream); + m_pSingleStream->LoadAllDataFiltered(); + m_CurrentStage = Stage::kPrepareContent; return; } @@ -107,10 +106,10 @@ CPDF_ContentParser::CPDF_ContentParser(CPDF_Form* pForm, pState->SetFillAlpha(1.0f); pState->SetSoftMask(nullptr); } - RetainPtr<CPDF_StreamAcc> pSingleStream = - pdfium::MakeRetain<CPDF_StreamAcc>(pForm->GetStream()); - pSingleStream->LoadAllDataFiltered(); - m_StreamArray.push_back(pSingleStream); + m_pSingleStream = pdfium::MakeRetain<CPDF_StreamAcc>(pForm->GetStream()); + m_pSingleStream->LoadAllDataFiltered(); + m_pData.Reset(m_pSingleStream->GetData()); + m_Size = m_pSingleStream->GetSize(); } CPDF_ContentParser::~CPDF_ContentParser() {} @@ -125,6 +124,9 @@ bool CPDF_ContentParser::Continue(PauseIndicatorIface* pPause) { return true; } + if (m_CurrentStage == Stage::kPrepareContent) + m_CurrentStage = PrepareContent(); + while (m_CurrentStage == Stage::kParse) { m_CurrentStage = Parse(); if (pPause && pPause->NeedToPauseNow()) @@ -148,12 +150,40 @@ CPDF_ContentParser::Stage CPDF_ContentParser::GetContent() { m_StreamArray[m_CurrentOffset]->LoadAllDataFiltered(); m_CurrentOffset++; - if (m_CurrentOffset >= m_nStreams) { - m_CurrentOffset = 0; + return m_CurrentOffset == m_nStreams ? Stage::kPrepareContent + : Stage::kGetContent; +} + +CPDF_ContentParser::Stage CPDF_ContentParser::PrepareContent() { + m_CurrentOffset = 0; + + if (m_StreamArray.empty()) { + m_pData.Reset(m_pSingleStream->GetData()); + m_Size = m_pSingleStream->GetSize(); return Stage::kParse; } - return Stage::kGetContent; + FX_SAFE_UINT32 safeSize = 0; + for (const auto& stream : m_StreamArray) { + safeSize += stream->GetSize(); + safeSize += 1; + } + if (!safeSize.IsValid()) + return Stage::kComplete; + + m_Size = safeSize.ValueOrDie(); + m_pData.Reset( + std::unique_ptr<uint8_t, FxFreeDeleter>(FX_Alloc(uint8_t, m_Size))); + + uint32_t pos = 0; + for (const auto& stream : m_StreamArray) { + memcpy(m_pData.Get() + pos, stream->GetData(), stream->GetSize()); + pos += stream->GetSize(); + m_pData.Get()[pos++] = ' '; + } + m_StreamArray.clear(); + + return Stage::kParse; } CPDF_ContentParser::Stage CPDF_ContentParser::Parse() { @@ -166,19 +196,12 @@ CPDF_ContentParser::Stage CPDF_ContentParser::Parse() { nullptr, m_parsedSet.get()); m_pParser->GetCurStates()->m_ColorState.SetDefault(); } + if (m_CurrentOffset >= m_Size) + return Stage::kCheckClip; - m_CurrentOffset += m_pParser->Parse( - m_StreamArray[m_CurrentStream]->GetData() + m_CurrentOffset, - m_StreamArray[m_CurrentStream]->GetSize() - m_CurrentOffset, - PARSE_STEP_LIMIT); - - if (m_CurrentOffset >= m_StreamArray[m_CurrentStream]->GetSize()) { - m_CurrentOffset = 0; - ++m_CurrentStream; - if (m_CurrentStream >= m_nStreams) - return Stage::kCheckClip; - } - + m_CurrentOffset += + m_pParser->Parse(m_pData.Get() + m_CurrentOffset, + m_Size - m_CurrentOffset, PARSE_STEP_LIMIT); return Stage::kParse; } diff --git a/core/fpdfapi/page/cpdf_contentparser.h b/core/fpdfapi/page/cpdf_contentparser.h index 92a3e06890..f9b491defa 100644 --- a/core/fpdfapi/page/cpdf_contentparser.h +++ b/core/fpdfapi/page/cpdf_contentparser.h @@ -42,22 +42,26 @@ class CPDF_ContentParser { private: enum class Stage : uint8_t { kGetContent = 1, + kPrepareContent, kParse, kCheckClip, kComplete, }; Stage GetContent(); + Stage PrepareContent(); Stage Parse(); Stage CheckClip(); Stage m_CurrentStage; UnownedPtr<CPDF_PageObjectHolder> const m_pObjectHolder; UnownedPtr<CPDF_Type3Char> m_pType3Char; // Only used when parsing forms. + RetainPtr<CPDF_StreamAcc> m_pSingleStream; std::vector<RetainPtr<CPDF_StreamAcc>> m_StreamArray; + MaybeOwned<uint8_t, FxFreeDeleter> m_pData; uint32_t m_nStreams = 0; + uint32_t m_Size = 0; uint32_t m_CurrentOffset = 0; - uint32_t m_CurrentStream = 0; // Only used when parsing pages. std::unique_ptr<std::set<const uint8_t*>> m_parsedSet; |