Ensure CPDF_Stream's dictionary is always a direct object
Make CPDF_Stream behave closer to the PDF spec. Add a deliberately bad
pixel test, which is similar to hello_world.pdf, to verify the existing
parser code already handles this case correctly.
Bug: pdfium:2119
Change-Id: Iabd791c2b3b8fa31433fb257f580868c06e16922
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/115693
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_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index d1fa557..0cb4b1e 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -53,7 +53,7 @@
CPDF_Stream::CPDF_Stream(RetainPtr<IFX_SeekableReadStream> file,
RetainPtr<CPDF_Dictionary> dict)
: data_(std::move(file)), dict_(std::move(dict)) {
- CHECK(dict_);
+ CHECK(dict_->IsInline());
SetLengthInDict(pdfium::base::checked_cast<int>(
absl::get<RetainPtr<IFX_SeekableReadStream>>(data_)->GetSize()));
}
@@ -61,7 +61,7 @@
CPDF_Stream::CPDF_Stream(DataVector<uint8_t> data,
RetainPtr<CPDF_Dictionary> dict)
: data_(std::move(data)), dict_(std::move(dict)) {
- CHECK(dict_);
+ CHECK(dict_->IsInline());
SetLengthInDict(pdfium::base::checked_cast<int>(
absl::get<DataVector<uint8_t>>(data_).size()));
}
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
index 42f5683..2311bf2 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`.
- // `dict` must be non-null.
+ // `dict` must be non-null and be a direct object.
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`.
- // `dict` must be non-null.
+ // `dict` must be non-null and be a direct object.
CPDF_Stream(RetainPtr<IFX_SeekableReadStream> file,
RetainPtr<CPDF_Dictionary> dict);
// Takes `data`.
- // `dict` must be non-null.
+ // `dict` must be non-null and be a direct object.
CPDF_Stream(DataVector<uint8_t> data, RetainPtr<CPDF_Dictionary> dict);
~CPDF_Stream() override;
diff --git a/testing/resources/pixel/stream_with_indirect_dict.in b/testing/resources/pixel/stream_with_indirect_dict.in
new file mode 100644
index 0000000..d882577
--- /dev/null
+++ b/testing/resources/pixel/stream_with_indirect_dict.in
@@ -0,0 +1,57 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /MediaBox [0 0 200 200]
+ /Count 1
+ /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 4 0 R
+ /F2 5 0 R
+ >>
+ >>
+ /Contents 6 0 R
+>>
+endobj
+{{object 4 0}} <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Times-Roman
+>>
+endobj
+{{object 5 0}} <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Helvetica
+>>
+endobj
+{{object 6 0}} 7 0 R
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(Hello, world!) Tj
+0 50 Td
+/F2 16 Tf
+(Goodbye, world!) Tj
+ET
+endstream
+endobj
+{{object 7 0}} <<
+ /Length 83
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/stream_with_indirect_dict_expected.pdf.0.png b/testing/resources/pixel/stream_with_indirect_dict_expected.pdf.0.png
new file mode 100644
index 0000000..f97e340
--- /dev/null
+++ b/testing/resources/pixel/stream_with_indirect_dict_expected.pdf.0.png
Binary files differ