Use MaybeOwned in CPDF_StreamAcc.

Change-Id: Iba886e51cf34ea01ed0d93afc93c8ec0ffed4f52
Reviewed-on: https://pdfium-review.googlesource.com/42594
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_stream_acc.cpp b/core/fpdfapi/parser/cpdf_stream_acc.cpp
index 1b097b5..7956124 100644
--- a/core/fpdfapi/parser/cpdf_stream_acc.cpp
+++ b/core/fpdfapi/parser/cpdf_stream_acc.cpp
@@ -6,15 +6,14 @@
 
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 
+#include <utility>
+
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
 
 CPDF_StreamAcc::CPDF_StreamAcc(const CPDF_Stream* pStream)
     : m_pStream(pStream) {}
 
-CPDF_StreamAcc::~CPDF_StreamAcc() {
-  if (m_bNewBuf)
-    FX_Free(m_pData);
-}
+CPDF_StreamAcc::~CPDF_StreamAcc() = default;
 
 void CPDF_StreamAcc::LoadAllData(bool bRawAccess,
                                  uint32_t estimated_size,
@@ -56,27 +55,26 @@
 }
 
 uint8_t* CPDF_StreamAcc::GetData() const {
-  if (m_bNewBuf)
-    return m_pData;
+  if (m_pData.IsOwned())
+    return m_pData.Get();
   return m_pStream ? m_pStream->GetInMemoryRawData() : nullptr;
 }
 
 uint32_t CPDF_StreamAcc::GetSize() const {
-  if (m_bNewBuf)
+  if (m_pData.IsOwned())
     return m_dwSize;
   return (m_pStream && m_pStream->IsMemoryBased()) ? m_pStream->GetRawSize()
                                                    : 0;
 }
 
 std::unique_ptr<uint8_t, FxFreeDeleter> CPDF_StreamAcc::DetachData() {
-  if (m_bNewBuf) {
-    std::unique_ptr<uint8_t, FxFreeDeleter> p(m_pData);
-    m_pData = nullptr;
+  if (m_pData.IsOwned()) {
+    std::unique_ptr<uint8_t, FxFreeDeleter> p = m_pData.ReleaseAndClear();
     m_dwSize = 0;
     return p;
   }
   std::unique_ptr<uint8_t, FxFreeDeleter> p(FX_Alloc(uint8_t, m_dwSize));
-  memcpy(p.get(), m_pData, m_dwSize);
+  memcpy(p.get(), m_pData.Get(), m_dwSize);
   return p;
 }
 
@@ -95,9 +93,8 @@
   if (!pData)
     return;
 
-  m_pData = pData.release();
+  m_pData = std::move(pData);
   m_dwSize = dwSrcSize;
-  m_bNewBuf = true;
 }
 
 void CPDF_StreamAcc::ProcessFilteredData(uint32_t estimated_size,
@@ -106,7 +103,7 @@
   if (dwSrcSize == 0)
     return;
 
-  uint8_t* pSrcData;
+  MaybeOwned<uint8_t, FxFreeDeleter> pSrcData;
   if (m_pStream->IsMemoryBased()) {
     pSrcData = m_pStream->GetInMemoryRawData();
   } else {
@@ -114,18 +111,30 @@
     if (!pTempSrcData)
       return;
 
-    pSrcData = pTempSrcData.release();
+    pSrcData = std::move(pTempSrcData);
   }
 
-  if (!PDF_DataDecode({pSrcData, dwSrcSize}, m_pStream->GetDict(),
-                      estimated_size, bImageAcc, &m_pData, &m_dwSize,
+  uint8_t* pDecodedData = nullptr;
+  uint32_t dwDecodedSize = 0;
+  if (!PDF_DataDecode({pSrcData.Get(), dwSrcSize}, m_pStream->GetDict(),
+                      estimated_size, bImageAcc, &pDecodedData, &dwDecodedSize,
                       &m_ImageDecoder, &m_pImageParam)) {
-    m_pData = pSrcData;
+    m_pData = std::move(pSrcData);
     m_dwSize = dwSrcSize;
+    return;
   }
-  if (pSrcData != m_pStream->GetInMemoryRawData() && pSrcData != m_pData)
-    FX_Free(pSrcData);
-  m_bNewBuf = m_pData != m_pStream->GetInMemoryRawData();
+
+  if (!pDecodedData)
+    return;
+
+  if (pDecodedData == pSrcData.Get()) {
+    m_pData = std::move(pSrcData);
+    m_dwSize = dwSrcSize;
+  } else {
+    std::unique_ptr<uint8_t, FxFreeDeleter> p(pDecodedData);
+    m_pData = std::move(p);
+    m_dwSize = dwDecodedSize;
+  }
 }
 
 std::unique_ptr<uint8_t, FxFreeDeleter> CPDF_StreamAcc::ReadRawStream() const {
diff --git a/core/fpdfapi/parser/cpdf_stream_acc.h b/core/fpdfapi/parser/cpdf_stream_acc.h
index 611c78d..e725041 100644
--- a/core/fpdfapi/parser/cpdf_stream_acc.h
+++ b/core/fpdfapi/parser/cpdf_stream_acc.h
@@ -13,6 +13,7 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/maybe_owned.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "third_party/base/span.h"
 
@@ -53,9 +54,8 @@
   // Reads the raw data from |m_pStream|, or return nullptr on failure.
   std::unique_ptr<uint8_t, FxFreeDeleter> ReadRawStream() const;
 
-  uint8_t* m_pData = nullptr;
+  MaybeOwned<uint8_t, FxFreeDeleter> m_pData;
   uint32_t m_dwSize = 0;
-  bool m_bNewBuf = false;
   ByteString m_ImageDecoder;
   UnownedPtr<const CPDF_Dictionary> m_pImageParam;
   UnownedPtr<const CPDF_Stream> const m_pStream;
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index 7ea49cf..cca28bc 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -386,9 +386,12 @@
     ByteString sFormName = ByteString::Format("F%d", i);
     pXObject->SetFor(sFormName, pObj->MakeReference(pDocument));
 
-    auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pNewXObject);
-    pAcc->LoadAllDataFiltered();
-    ByteString sStream(pAcc->GetData(), pAcc->GetSize());
+    ByteString sStream;
+    {
+      auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pNewXObject);
+      pAcc->LoadAllDataFiltered();
+      sStream = ByteString(pAcc->GetSpan());
+    }
     CFX_Matrix matrix = pAPDic->GetMatrixFor("Matrix");
     CFX_Matrix m = GetMatrix(rcAnnot, rcStream, matrix);
     sStream += ByteString::Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d,