Avoid writing out empty streams in CPDF_Stream::WriteTo().
Do not call CFX_FileBufferArchive::WriteBlock() with no data to write
out to avoid an ASSERT() failure. Although
CFX_FileBufferArchive::WriteBlock() can handle no data just fine, it is
an IFX_WriteStream::WriteBlock() implementation and not all
IFX_WriteStream::WriteBlock() implementations can handle no data.
BUG=chromium:905142
Change-Id: Icef8460443a9363526679261aac0c1ef74bccec4
Reviewed-on: https://pdfium-review.googlesource.com/c/45531
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index 11ea67e..db38c41 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -192,20 +192,24 @@
data = encrypted_data;
}
- if (static_cast<uint32_t>(encoder.GetDict()->GetIntegerFor("Length")) !=
- data.size()) {
+ size_t size = data.size();
+ if (static_cast<size_t>(encoder.GetDict()->GetIntegerFor("Length")) != size) {
encoder.CloneDict();
- encoder.GetClonedDict()->SetNewFor<CPDF_Number>(
- "Length", static_cast<int>(data.size()));
+ encoder.GetClonedDict()->SetNewFor<CPDF_Number>("Length",
+ static_cast<int>(size));
}
if (!encoder.GetDict()->WriteTo(archive, encryptor))
return false;
- if (!archive->WriteString("stream\r\n") ||
- !archive->WriteBlock(data.data(), data.size()) ||
- !archive->WriteString("\r\nendstream")) {
+ if (!archive->WriteString("stream\r\n"))
return false;
- }
+
+ if (size && !archive->WriteBlock(data.data(), size))
+ return false;
+
+ if (!archive->WriteString("\r\nendstream"))
+ return false;
+
return true;
}
diff --git a/fpdfsdk/fpdf_save_embeddertest.cpp b/fpdfsdk/fpdf_save_embeddertest.cpp
index 510660e..46d165c 100644
--- a/fpdfsdk/fpdf_save_embeddertest.cpp
+++ b/fpdfsdk/fpdf_save_embeddertest.cpp
@@ -100,3 +100,9 @@
EXPECT_THAT(GetString(),
testing::Not(testing::HasSubstr("0000000000 65536 f\r\n")));
}
+
+TEST_F(FPDFSaveEmbedderTest, BUG_905142) {
+ EXPECT_TRUE(OpenDocument("bug_905142.pdf"));
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ EXPECT_THAT(GetString(), testing::HasSubstr("/Length 0"));
+}
diff --git a/testing/resources/bug_905142.in b/testing/resources/bug_905142.in
new file mode 100644
index 0000000..d37f68f
--- /dev/null
+++ b/testing/resources/bug_905142.in
@@ -0,0 +1,31 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Kids [ 3 0 R ]
+ /Count 1
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 1 0 R
+ /Contents [ 4 0 R ]
+ /MediaBox [ 0 0 612 792 ]
+>>
+endobj
+{{object 4 0}} <<
+ /Filter /FlateDecode
+ /Length 0
+>>
+stream
+
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_905142.pdf b/testing/resources/bug_905142.pdf
new file mode 100644
index 0000000..9f2898f
--- /dev/null
+++ b/testing/resources/bug_905142.pdf
@@ -0,0 +1,42 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /Kids [ 3 0 R ]
+ /Count 1
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 1 0 R
+ /Contents [ 4 0 R ]
+ /MediaBox [ 0 0 612 792 ]
+>>
+endobj
+4 0 obj <<
+ /Filter /FlateDecode
+ /Length 0
+>>
+stream
+
+endstream
+endobj
+xref
+0 5
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000133 00000 n
+0000000234 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 5
+>>
+startxref
+308
+%%EOF