Ensure CPDF_Stream always has a dictionary

Now that CPDF_Stream is never uninitialized, tweak its semantics to
guarantee its `dict_` member is never null and CHECK() that is the case.
Then remove conditionals that check if `dict_` is null, and update known
CPDF_Stream users to avoid passing in null dictionaries.

Change-Id: I3446698401cbc29c7100a18084997e02e8030de4
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/115692
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fpdfapi/parser/cpdf_object_stream_unittest.cpp b/core/fpdfapi/parser/cpdf_object_stream_unittest.cpp
index 43306f4..513ca9b 100644
--- a/core/fpdfapi/parser/cpdf_object_stream_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_stream_unittest.cpp
@@ -80,11 +80,11 @@
   EXPECT_FALSE(obj_stream->ParseObject(&holder, 12, 3));
 }
 
-TEST(ObjectStreamTest, StreamNoDict) {
+TEST(ObjectStreamTest, StreamEmptyDict) {
   ByteStringView contents_view(kNormalStreamContent);
   auto stream = pdfium::MakeRetain<CPDF_Stream>(
       DataVector<uint8_t>(contents_view.begin(), contents_view.end()),
-      /*pDict=*/nullptr);
+      pdfium::MakeRetain<CPDF_Dictionary>());
   EXPECT_FALSE(CPDF_ObjectStream::Create(std::move(stream)));
 }
 
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index acda825..cfa7dfc 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -23,6 +23,7 @@
 #include "core/fxcrt/data_vector.h"
 #include "core/fxcrt/fx_stream.h"
 #include "core/fxcrt/span_util.h"
+#include "third_party/base/check.h"
 #include "third_party/base/containers/contains.h"
 #include "third_party/base/numerics/safe_conversions.h"
 
@@ -52,6 +53,7 @@
 CPDF_Stream::CPDF_Stream(RetainPtr<IFX_SeekableReadStream> file,
                          RetainPtr<CPDF_Dictionary> dict)
     : data_(std::move(file)), dict_(std::move(dict)) {
+  CHECK(dict_);
   SetLengthInDict(pdfium::base::checked_cast<int>(
       absl::get<RetainPtr<IFX_SeekableReadStream>>(data_)->GetSize()));
 }
@@ -59,14 +61,16 @@
 CPDF_Stream::CPDF_Stream(DataVector<uint8_t> data,
                          RetainPtr<CPDF_Dictionary> dict)
     : data_(std::move(data)), dict_(std::move(dict)) {
+  CHECK(dict_);
   SetLengthInDict(pdfium::base::checked_cast<int>(
       absl::get<DataVector<uint8_t>>(data_).size()));
 }
 
 CPDF_Stream::~CPDF_Stream() {
   m_ObjNum = kInvalidObjNum;
-  if (dict_ && dict_->GetObjNum() == kInvalidObjNum)
+  if (dict_->GetObjNum() == kInvalidObjNum) {
     dict_.Leak();  // lowercase release, release ownership.
+  }
 }
 
 CPDF_Object::Type CPDF_Stream::GetType() const {
@@ -161,7 +165,7 @@
 }
 
 bool CPDF_Stream::HasFilter() const {
-  return dict_ && dict_->KeyExist("Filter");
+  return dict_->KeyExist("Filter");
 }
 
 WideString CPDF_Stream::GetUnicodeText() const {
@@ -209,7 +213,5 @@
 }
 
 void CPDF_Stream::SetLengthInDict(int length) {
-  if (!dict_)
-    dict_ = pdfium::MakeRetain<CPDF_Dictionary>();
   dict_->SetNewFor<CPDF_Number>("Length", length);
 }
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
index 08b72ed..42f5683 100644
--- a/core/fpdfapi/parser/cpdf_stream.h
+++ b/core/fpdfapi/parser/cpdf_stream.h
@@ -68,7 +68,7 @@
   friend class CPDF_Dictionary;
 
   // Initializes with empty data and /Length set to 0 in `dict`.
-  // If `dict` is null, then a new dictionary will be created instead.
+  // `dict` must be non-null.
   explicit CPDF_Stream(RetainPtr<CPDF_Dictionary> dict);
 
   // Copies `span` and `stream`, respectively. Creates a new dictionary with the
@@ -77,12 +77,12 @@
   explicit CPDF_Stream(fxcrt::ostringstream* stream);
 
   // Reads data from `file`. `dict` will have its /Length set based on `file`.
-  // If `dict` is null, then a new dictionary will be created instead.
+  // `dict` must be non-null.
   CPDF_Stream(RetainPtr<IFX_SeekableReadStream> file,
               RetainPtr<CPDF_Dictionary> dict);
 
   // Takes `data`.
-  // If `dict` is null, then a new dictionary will be created instead.
+  // `dict` must be non-null.
   CPDF_Stream(DataVector<uint8_t> data, RetainPtr<CPDF_Dictionary> dict);
   ~CPDF_Stream() override;