Add RemoveTextObjectWithTwoPagesSharingContentStreamAndResources test
Add a test case to demonstrate FPDFPage_RemoveObject() not working
correctly when 2 pages share the same page /Content stream object.
Bug: pdfium:2012
Change-Id: I5fc0f0888d71368c0dd257931e4a1013301f639f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/105212
Reviewed-by: K. Moon <kmoon@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index ce462d4..a55873b 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -928,6 +928,66 @@
UnloadPage(page);
}
+TEST_F(FPDFEditEmbedderTest,
+ RemoveTextObjectWithTwoPagesSharingContentStreamAndResources) {
+ // Load document with some text.
+ ASSERT_TRUE(OpenDocument("hello_world_2_pages.pdf"));
+ FPDF_PAGE page1 = LoadPage(0);
+ ASSERT_TRUE(page1);
+ FPDF_PAGE page2 = LoadPage(1);
+ ASSERT_TRUE(page2);
+
+ // Show what the original file looks like.
+ {
+ ScopedFPDFBitmap page1_bitmap = RenderPage(page1);
+ CompareBitmap(page1_bitmap.get(), 200, 200, HelloWorldChecksum());
+ ScopedFPDFBitmap page2_bitmap = RenderPage(page2);
+ CompareBitmap(page2_bitmap.get(), 200, 200, HelloWorldChecksum());
+ }
+
+ // Get the "Hello, world!" text object from page 1 and remove it.
+ ASSERT_EQ(2, FPDFPage_CountObjects(page1));
+ {
+ ScopedFPDFPageObject page_object(FPDFPage_GetObject(page1, 0));
+ ASSERT_TRUE(page_object);
+ ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(page_object.get()));
+ EXPECT_TRUE(FPDFPage_RemoveObject(page1, page_object.get()));
+ }
+ ASSERT_EQ(1, FPDFPage_CountObjects(page1));
+
+ // Verify the "Hello, world!" text is gone from page 1.
+ {
+ ScopedFPDFBitmap page1_bitmap = RenderPage(page1);
+ CompareBitmap(page1_bitmap.get(), 200, 200, FirstRemovedChecksum());
+ ScopedFPDFBitmap page2_bitmap = RenderPage(page2);
+ CompareBitmap(page2_bitmap.get(), 200, 200, HelloWorldChecksum());
+ }
+
+ // Verify the rendering again after calling FPDFPage_GenerateContent().
+ ASSERT_TRUE(FPDFPage_GenerateContent(page1));
+ {
+ ScopedFPDFBitmap page1_bitmap = RenderPage(page1);
+ CompareBitmap(page1_bitmap.get(), 200, 200, FirstRemovedChecksum());
+ ScopedFPDFBitmap page2_bitmap = RenderPage(page2);
+ CompareBitmap(page2_bitmap.get(), 200, 200, HelloWorldChecksum());
+ }
+
+ // Save the document and verify it after reloading.
+ ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ ASSERT_TRUE(OpenSavedDocument());
+ FPDF_PAGE saved_page1 = LoadSavedPage(0);
+ VerifySavedRendering(saved_page1, 200, 200, FirstRemovedChecksum());
+ CloseSavedPage(saved_page1);
+ FPDF_PAGE saved_page2 = LoadSavedPage(1);
+ // TODO(crbug.com/pdfium/2012): Should be `HelloWorldChecksum()`.
+ VerifySavedRendering(saved_page2, 200, 200, FirstRemovedChecksum());
+ CloseSavedPage(saved_page2);
+ CloseSavedDocument();
+
+ UnloadPage(page1);
+ UnloadPage(page2);
+}
+
void CheckMarkCounts(FPDF_PAGE page,
int start_from,
int expected_object_count,
diff --git a/testing/resources/hello_world_2_pages.in b/testing/resources/hello_world_2_pages.in
new file mode 100644
index 0000000..ec33354
--- /dev/null
+++ b/testing/resources/hello_world_2_pages.in
@@ -0,0 +1,67 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 2
+ /Kids [3 0 R 4 0 R]
+ /MediaBox [0 0 200 200]
+>>
+endobj
+{{object 3 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 5 0 R
+ /F2 6 0 R
+ >>
+ >>
+ /Contents 7 0 R
+>>
+endobj
+{{object 4 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 5 0 R
+ /F2 6 0 R
+ >>
+ >>
+ /Contents 7 0 R
+>>
+endobj
+{{object 5 0}} <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Times-Roman
+>>
+endobj
+{{object 6 0}} <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Helvetica
+>>
+endobj
+{{object 7 0}} <<
+ {{streamlen}}
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(Hello, world!) Tj
+0 50 Td
+/F2 16 Tf
+(Goodbye, world!) Tj
+ET
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/hello_world_2_pages.pdf b/testing/resources/hello_world_2_pages.pdf
new file mode 100644
index 0000000..4942e3a
--- /dev/null
+++ b/testing/resources/hello_world_2_pages.pdf
@@ -0,0 +1,81 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /MediaBox [0 0 200 200]
+ /Count 2
+ /Kids [3 0 R 4 0 R]
+>>
+endobj
+3 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 5 0 R
+ /F2 6 0 R
+ >>
+ >>
+ /Contents 7 0 R
+>>
+endobj
+4 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /Resources <<
+ /Font <<
+ /F1 5 0 R
+ /F2 6 0 R
+ >>
+ >>
+ /Contents 7 0 R
+>>
+endobj
+5 0 obj <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Times-Roman
+>>
+endobj
+6 0 obj <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Helvetica
+>>
+endobj
+7 0 obj <<
+ /Length 83
+>>
+stream
+BT
+20 50 Td
+/F1 12 Tf
+(Hello, world!) Tj
+0 50 Td
+/F2 16 Tf
+(Goodbye, world!) Tj
+ET
+endstream
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+0000000163 00000 n
+0000000305 00000 n
+0000000447 00000 n
+0000000525 00000 n
+0000000601 00000 n
+trailer <<
+ /Root 1 0 R
+ /Size 8
+>>
+startxref
+735
+%%EOF