• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <iterator>
6 
7 #include "core/fpdfapi/page/cpdf_form.h"
8 #include "core/fpdfapi/page/cpdf_formobject.h"
9 #include "core/fpdfapi/parser/cpdf_array.h"
10 #include "core/fpdfapi/parser/cpdf_dictionary.h"
11 #include "core/fpdfapi/parser/cpdf_document.h"
12 #include "core/fpdfapi/parser/cpdf_name.h"
13 #include "core/fpdfapi/parser/cpdf_number.h"
14 #include "core/fpdfapi/parser/cpdf_stream.h"
15 #include "core/fpdfapi/parser/cpdf_string.h"
16 #include "core/fxge/cfx_defaultrenderdevice.h"
17 #include "fpdfsdk/cpdfsdk_helpers.h"
18 #include "public/cpp/fpdf_scopers.h"
19 #include "public/fpdf_edit.h"
20 #include "public/fpdf_ppo.h"
21 #include "public/fpdf_save.h"
22 #include "public/fpdfview.h"
23 #include "testing/embedder_test.h"
24 #include "testing/embedder_test_constants.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 
27 namespace {
28 
29 class FPDFPPOEmbedderTest : public EmbedderTest {};
30 
FakeBlockWriter(FPDF_FILEWRITE * pThis,const void * pData,unsigned long size)31 int FakeBlockWriter(FPDF_FILEWRITE* pThis,
32                     const void* pData,
33                     unsigned long size) {
34   return 1;  // Always succeeds.
35 }
36 
37 constexpr int kRectanglesMultiPagesPageCount = 2;
38 
RectanglesMultiPagesExpectedChecksum(int page_index)39 const char* RectanglesMultiPagesExpectedChecksum(int page_index) {
40   if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
41     static constexpr const char* kChecksums[kRectanglesMultiPagesPageCount] = {
42         "07606a12487bd0c28a88f23fa00fc313", "94ea6e1eef220833a3ec14d6a1c612b0"};
43     return kChecksums[page_index];
44   }
45   static constexpr const char* kChecksums[kRectanglesMultiPagesPageCount] = {
46       "72d0d7a19a2f40e010ca6a1133b33e1e", "fb18142190d770cfbc329d2b071aee4d"};
47   return kChecksums[page_index];
48 }
49 
Bug750568PageHash(int page_index)50 const char* Bug750568PageHash(int page_index) {
51   constexpr int kBug750568PageCount = 4;
52   if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
53     static constexpr const char* kChecksums[kBug750568PageCount] = {
54         "eaa139e944eafb43d31e8742a0e158de", "226485e9d4fa6a67dfe0a88723f12060",
55         "c5601a3492ae5dcc5dd25140fc463bfe", "1f60055b54de4fac8a59c65e90da156e"};
56     return kChecksums[page_index];
57   }
58   static constexpr const char* kChecksums[kBug750568PageCount] = {
59       "64ad08132a1c5a166768298c8a578f57", "83b83e2f6bc80707d0a917c7634140b9",
60       "913cd3723a451e4e46fbc2c05702d1ee", "81fb7cfd4860f855eb468f73dfeb6d60"};
61   return kChecksums[page_index];
62 }
63 
64 }  // namespace
65 
TEST_F(FPDFPPOEmbedderTest,NoViewerPreferences)66 TEST_F(FPDFPPOEmbedderTest, NoViewerPreferences) {
67   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
68 
69   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
70   EXPECT_TRUE(output_doc);
71   EXPECT_FALSE(FPDF_CopyViewerPreferences(output_doc, document()));
72   FPDF_CloseDocument(output_doc);
73 }
74 
TEST_F(FPDFPPOEmbedderTest,ViewerPreferences)75 TEST_F(FPDFPPOEmbedderTest, ViewerPreferences) {
76   ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
77 
78   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
79   EXPECT_TRUE(output_doc);
80   EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
81   FPDF_CloseDocument(output_doc);
82 }
83 
TEST_F(FPDFPPOEmbedderTest,ImportPagesByIndex)84 TEST_F(FPDFPPOEmbedderTest, ImportPagesByIndex) {
85   ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
86 
87   FPDF_PAGE page = LoadPage(0);
88   EXPECT_TRUE(page);
89 
90   ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
91   ASSERT_TRUE(output_doc);
92   EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
93 
94   static constexpr int kPageIndices[] = {1};
95   EXPECT_TRUE(FPDF_ImportPagesByIndex(
96       output_doc.get(), document(), kPageIndices, std::size(kPageIndices), 0));
97   EXPECT_EQ(1, FPDF_GetPageCount(output_doc.get()));
98 
99   UnloadPage(page);
100 }
101 
TEST_F(FPDFPPOEmbedderTest,ImportPages)102 TEST_F(FPDFPPOEmbedderTest, ImportPages) {
103   ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
104 
105   FPDF_PAGE page = LoadPage(0);
106   EXPECT_TRUE(page);
107 
108   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
109   ASSERT_TRUE(output_doc);
110   EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
111   EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "1", 0));
112   EXPECT_EQ(1, FPDF_GetPageCount(output_doc));
113   FPDF_CloseDocument(output_doc);
114 
115   UnloadPage(page);
116 }
117 
TEST_F(FPDFPPOEmbedderTest,ImportNPages)118 TEST_F(FPDFPPOEmbedderTest, ImportNPages) {
119   ASSERT_TRUE(OpenDocument("rectangles_multi_pages.pdf"));
120 
121   ScopedFPDFDocument output_doc_2up(
122       FPDF_ImportNPagesToOne(document(), 612, 792, 2, 1));
123   ASSERT_TRUE(output_doc_2up);
124   EXPECT_EQ(3, FPDF_GetPageCount(output_doc_2up.get()));
125   ScopedFPDFDocument output_doc_5up(
126       FPDF_ImportNPagesToOne(document(), 612, 792, 5, 1));
127   ASSERT_TRUE(output_doc_5up);
128   EXPECT_EQ(1, FPDF_GetPageCount(output_doc_5up.get()));
129   ScopedFPDFDocument output_doc_8up(
130       FPDF_ImportNPagesToOne(document(), 792, 612, 8, 1));
131   ASSERT_TRUE(output_doc_8up);
132   EXPECT_EQ(1, FPDF_GetPageCount(output_doc_8up.get()));
133   ScopedFPDFDocument output_doc_128up(
134       FPDF_ImportNPagesToOne(document(), 792, 612, 128, 1));
135   ASSERT_TRUE(output_doc_128up);
136   EXPECT_EQ(1, FPDF_GetPageCount(output_doc_128up.get()));
137 }
138 
TEST_F(FPDFPPOEmbedderTest,BadNupParams)139 TEST_F(FPDFPPOEmbedderTest, BadNupParams) {
140   ASSERT_TRUE(OpenDocument("rectangles_multi_pages.pdf"));
141 
142   FPDF_DOCUMENT output_doc_zero_row =
143       FPDF_ImportNPagesToOne(document(), 612, 792, 0, 3);
144   ASSERT_FALSE(output_doc_zero_row);
145   FPDF_DOCUMENT output_doc_zero_col =
146       FPDF_ImportNPagesToOne(document(), 612, 792, 2, 0);
147   ASSERT_FALSE(output_doc_zero_col);
148   FPDF_DOCUMENT output_doc_zero_width =
149       FPDF_ImportNPagesToOne(document(), 0, 792, 2, 1);
150   ASSERT_FALSE(output_doc_zero_width);
151   FPDF_DOCUMENT output_doc_zero_height =
152       FPDF_ImportNPagesToOne(document(), 612, 0, 7, 1);
153   ASSERT_FALSE(output_doc_zero_height);
154 }
155 
156 // TODO(Xlou): Add more tests to check output doc content of
157 // FPDF_ImportNPagesToOne()
TEST_F(FPDFPPOEmbedderTest,NupRenderImage)158 TEST_F(FPDFPPOEmbedderTest, NupRenderImage) {
159   ASSERT_TRUE(OpenDocument("rectangles_multi_pages.pdf"));
160   ScopedFPDFDocument output_doc_3up(
161       FPDF_ImportNPagesToOne(document(), 792, 612, 3, 1));
162   ASSERT_TRUE(output_doc_3up);
163   ASSERT_EQ(kRectanglesMultiPagesPageCount,
164             FPDF_GetPageCount(output_doc_3up.get()));
165   for (int i = 0; i < kRectanglesMultiPagesPageCount; ++i) {
166     ScopedFPDFPage page(FPDF_LoadPage(output_doc_3up.get(), i));
167     ASSERT_TRUE(page);
168     ScopedFPDFBitmap bitmap = RenderPage(page.get());
169     EXPECT_EQ(792, FPDFBitmap_GetWidth(bitmap.get()));
170     EXPECT_EQ(612, FPDFBitmap_GetHeight(bitmap.get()));
171     EXPECT_EQ(RectanglesMultiPagesExpectedChecksum(i),
172               HashBitmap(bitmap.get()));
173   }
174 }
175 
TEST_F(FPDFPPOEmbedderTest,ImportPageToXObject)176 TEST_F(FPDFPPOEmbedderTest, ImportPageToXObject) {
177   const char* checksum = []() {
178     if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
179       return "d6ebc0a8afc22fe0137f54ce54e1a19c";
180     return "2d88d180af7109eb346439f7c855bb29";
181   }();
182 
183   ASSERT_TRUE(OpenDocument("rectangles.pdf"));
184 
185   {
186     ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
187     ASSERT_TRUE(output_doc);
188 
189     FPDF_XOBJECT xobject =
190         FPDF_NewXObjectFromPage(output_doc.get(), document(), 0);
191     ASSERT_TRUE(xobject);
192 
193     for (int i = 0; i < 2; ++i) {
194       ScopedFPDFPage page(FPDFPage_New(output_doc.get(), 0, 612, 792));
195       ASSERT_TRUE(page);
196 
197       FPDF_PAGEOBJECT page_object = FPDF_NewFormObjectFromXObject(xobject);
198       ASSERT_TRUE(page_object);
199       EXPECT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(page_object));
200       FPDFPage_InsertObject(page.get(), page_object);
201       EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
202 
203       ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
204       CompareBitmap(page_bitmap.get(), 612, 792, checksum);
205 
206       float left;
207       float bottom;
208       float right;
209       float top;
210       ASSERT_TRUE(
211           FPDFPageObj_GetBounds(page_object, &left, &bottom, &right, &top));
212       EXPECT_FLOAT_EQ(-1.0f, left);
213       EXPECT_FLOAT_EQ(-1.0f, bottom);
214       EXPECT_FLOAT_EQ(201.0f, right);
215       EXPECT_FLOAT_EQ(301.0f, top);
216     }
217 
218     EXPECT_TRUE(FPDF_SaveAsCopy(output_doc.get(), this, 0));
219 
220     FPDF_CloseXObject(xobject);
221   }
222 
223   constexpr int kExpectedPageCount = 2;
224   ASSERT_TRUE(OpenSavedDocument());
225 
226   FPDF_PAGE saved_pages[kExpectedPageCount];
227   FPDF_PAGEOBJECT xobjects[kExpectedPageCount];
228   for (int i = 0; i < kExpectedPageCount; ++i) {
229     saved_pages[i] = LoadSavedPage(i);
230     ASSERT_TRUE(saved_pages[i]);
231 
232     EXPECT_EQ(1, FPDFPage_CountObjects(saved_pages[i]));
233     xobjects[i] = FPDFPage_GetObject(saved_pages[i], 0);
234     ASSERT_TRUE(xobjects[i]);
235     ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(xobjects[i]));
236     EXPECT_EQ(8, FPDFFormObj_CountObjects(xobjects[i]));
237 
238     {
239       ScopedFPDFBitmap page_bitmap = RenderPage(saved_pages[i]);
240       CompareBitmap(page_bitmap.get(), 612, 792, checksum);
241     }
242   }
243 
244   for (int i = 0; i < kExpectedPageCount; ++i) {
245     float left;
246     float bottom;
247     float right;
248     float top;
249     ASSERT_TRUE(
250         FPDFPageObj_GetBounds(xobjects[i], &left, &bottom, &right, &top));
251     EXPECT_FLOAT_EQ(-1.0f, left);
252     EXPECT_FLOAT_EQ(-1.0f, bottom);
253     EXPECT_FLOAT_EQ(201.0f, right);
254     EXPECT_FLOAT_EQ(301.0f, top);
255   }
256 
257   // Peek at object internals to make sure the two XObjects use the same stream.
258   EXPECT_NE(xobjects[0], xobjects[1]);
259   CPDF_PageObject* obj1 = CPDFPageObjectFromFPDFPageObject(xobjects[0]);
260   ASSERT_TRUE(obj1->AsForm());
261   ASSERT_TRUE(obj1->AsForm()->form());
262   ASSERT_TRUE(obj1->AsForm()->form()->GetStream());
263   CPDF_PageObject* obj2 = CPDFPageObjectFromFPDFPageObject(xobjects[1]);
264   ASSERT_TRUE(obj2->AsForm());
265   ASSERT_TRUE(obj2->AsForm()->form());
266   ASSERT_TRUE(obj2->AsForm()->form()->GetStream());
267   EXPECT_EQ(obj1->AsForm()->form()->GetStream(),
268             obj2->AsForm()->form()->GetStream());
269 
270   for (FPDF_PAGE saved_page : saved_pages)
271     CloseSavedPage(saved_page);
272 
273   CloseSavedDocument();
274 }
275 
TEST_F(FPDFPPOEmbedderTest,ImportPageToXObjectWithSameDoc)276 TEST_F(FPDFPPOEmbedderTest, ImportPageToXObjectWithSameDoc) {
277   const char* checksum = []() {
278     if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
279       return "8e7d672f49f9ca98fb9157824cefc204";
280     return "4d5ca14827b7707f8283e639b33c121a";
281   }();
282 
283   ASSERT_TRUE(OpenDocument("rectangles.pdf"));
284 
285   FPDF_XOBJECT xobject = FPDF_NewXObjectFromPage(document(), document(), 0);
286   ASSERT_TRUE(xobject);
287 
288   FPDF_PAGE page = LoadPage(0);
289   ASSERT_TRUE(page);
290 
291   {
292     ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
293     CompareBitmap(bitmap.get(), 200, 300, pdfium::RectanglesChecksum());
294   }
295 
296   FPDF_PAGEOBJECT page_object = FPDF_NewFormObjectFromXObject(xobject);
297   ASSERT_TRUE(page_object);
298   ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(page_object));
299 
300   static constexpr FS_MATRIX kMatrix = {0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f};
301   EXPECT_TRUE(FPDFPageObj_SetMatrix(page_object, &kMatrix));
302 
303   FPDFPage_InsertObject(page, page_object);
304   EXPECT_TRUE(FPDFPage_GenerateContent(page));
305 
306   {
307     ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
308     CompareBitmap(bitmap.get(), 200, 300, checksum);
309   }
310 
311   FPDF_CloseXObject(xobject);
312 
313   EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
314   VerifySavedDocument(200, 300, checksum);
315 
316   UnloadPage(page);
317 }
318 
TEST_F(FPDFPPOEmbedderTest,XObjectNullParams)319 TEST_F(FPDFPPOEmbedderTest, XObjectNullParams) {
320   ASSERT_TRUE(OpenDocument("rectangles.pdf"));
321   ASSERT_EQ(1, FPDF_GetPageCount(document()));
322 
323   EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, nullptr, -1));
324   EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, nullptr, 0));
325   EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, nullptr, 1));
326   EXPECT_FALSE(FPDF_NewXObjectFromPage(document(), nullptr, -1));
327   EXPECT_FALSE(FPDF_NewXObjectFromPage(document(), nullptr, 0));
328   EXPECT_FALSE(FPDF_NewXObjectFromPage(document(), nullptr, 1));
329   EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, document(), -1));
330   EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, document(), 0));
331   EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, document(), 1));
332 
333   {
334     ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
335     ASSERT_TRUE(output_doc);
336     EXPECT_FALSE(FPDF_NewXObjectFromPage(output_doc.get(), document(), -1));
337     EXPECT_FALSE(FPDF_NewXObjectFromPage(output_doc.get(), document(), 1));
338   }
339 
340   // Should be a no-op.
341   FPDF_CloseXObject(nullptr);
342 
343   EXPECT_FALSE(FPDF_NewFormObjectFromXObject(nullptr));
344 }
345 
TEST_F(FPDFPPOEmbedderTest,BUG_925981)346 TEST_F(FPDFPPOEmbedderTest, BUG_925981) {
347   ASSERT_TRUE(OpenDocument("bug_925981.pdf"));
348   ScopedFPDFDocument output_doc_2up(
349       FPDF_ImportNPagesToOne(document(), 612, 792, 2, 1));
350   EXPECT_EQ(1, FPDF_GetPageCount(output_doc_2up.get()));
351 }
352 
TEST_F(FPDFPPOEmbedderTest,BUG_1229106)353 TEST_F(FPDFPPOEmbedderTest, BUG_1229106) {
354   static constexpr int kPageCount = 4;
355   static constexpr int kTwoUpPageCount = 2;
356   static const char kRectsChecksum[] = "140d629b3c96a07ced2e3e408ea85a1d";
357   static const char kTwoUpChecksum[] = "fa4501562301b2e75da354bd067495ec";
358 
359   ASSERT_TRUE(OpenDocument("bug_1229106.pdf"));
360 
361   // Show all pages render the same.
362   ASSERT_EQ(kPageCount, FPDF_GetPageCount(document()));
363   for (int i = 0; i < kPageCount; ++i) {
364     FPDF_PAGE page = LoadPage(0);
365     ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
366     CompareBitmap(bitmap.get(), 792, 612, kRectsChecksum);
367     UnloadPage(page);
368   }
369 
370   // Create a 2-up PDF.
371   ScopedFPDFDocument output_doc_2up(
372       FPDF_ImportNPagesToOne(document(), 612, 792, 1, 2));
373   ASSERT_EQ(kTwoUpPageCount, FPDF_GetPageCount(output_doc_2up.get()));
374   for (int i = 0; i < kTwoUpPageCount; ++i) {
375     ScopedFPDFPage page(FPDF_LoadPage(output_doc_2up.get(), i));
376     ScopedFPDFBitmap bitmap = RenderPage(page.get());
377     CompareBitmap(bitmap.get(), 612, 792, kTwoUpChecksum);
378   }
379 }
380 
TEST_F(FPDFPPOEmbedderTest,BadRepeatViewerPref)381 TEST_F(FPDFPPOEmbedderTest, BadRepeatViewerPref) {
382   ASSERT_TRUE(OpenDocument("repeat_viewer_ref.pdf"));
383 
384   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
385   EXPECT_TRUE(output_doc);
386   EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
387 
388   FPDF_FILEWRITE writer;
389   writer.version = 1;
390   writer.WriteBlock = FakeBlockWriter;
391 
392   EXPECT_TRUE(FPDF_SaveAsCopy(output_doc, &writer, 0));
393   FPDF_CloseDocument(output_doc);
394 }
395 
TEST_F(FPDFPPOEmbedderTest,BadCircularViewerPref)396 TEST_F(FPDFPPOEmbedderTest, BadCircularViewerPref) {
397   ASSERT_TRUE(OpenDocument("circular_viewer_ref.pdf"));
398 
399   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
400   EXPECT_TRUE(output_doc);
401   EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
402 
403   FPDF_FILEWRITE writer;
404   writer.version = 1;
405   writer.WriteBlock = FakeBlockWriter;
406 
407   EXPECT_TRUE(FPDF_SaveAsCopy(output_doc, &writer, 0));
408   FPDF_CloseDocument(output_doc);
409 }
410 
TEST_F(FPDFPPOEmbedderTest,CopyViewerPrefTypes)411 TEST_F(FPDFPPOEmbedderTest, CopyViewerPrefTypes) {
412   ASSERT_TRUE(OpenDocument("viewer_pref_types.pdf"));
413 
414   ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
415   ASSERT_TRUE(output_doc);
416   EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
417 
418   // Peek under the hook to check the result.
419   const CPDF_Document* output_doc_impl =
420       CPDFDocumentFromFPDFDocument(output_doc.get());
421   RetainPtr<const CPDF_Dictionary> prefs =
422       output_doc_impl->GetRoot()->GetDictFor("ViewerPreferences");
423   ASSERT_TRUE(prefs);
424   EXPECT_EQ(6u, prefs->size());
425 
426   RetainPtr<const CPDF_Object> bool_obj = prefs->GetObjectFor("Bool");
427   ASSERT_TRUE(bool_obj);
428   EXPECT_TRUE(bool_obj->IsBoolean());
429 
430   RetainPtr<const CPDF_Number> num_obj = prefs->GetNumberFor("Num");
431   ASSERT_TRUE(num_obj);
432   EXPECT_TRUE(num_obj->IsInteger());
433   EXPECT_EQ(1, num_obj->GetInteger());
434 
435   RetainPtr<const CPDF_String> str_obj = prefs->GetStringFor("Str");
436   ASSERT_TRUE(str_obj);
437   EXPECT_EQ("str", str_obj->GetString());
438 
439   EXPECT_EQ("name", prefs->GetNameFor("Name"));
440 
441   RetainPtr<const CPDF_Array> empty_array_obj =
442       prefs->GetArrayFor("EmptyArray");
443   ASSERT_TRUE(empty_array_obj);
444   EXPECT_TRUE(empty_array_obj->IsEmpty());
445 
446   RetainPtr<const CPDF_Array> good_array_obj = prefs->GetArrayFor("GoodArray");
447   ASSERT_TRUE(good_array_obj);
448   EXPECT_EQ(4u, good_array_obj->size());
449 }
450 
TEST_F(FPDFPPOEmbedderTest,BadIndices)451 TEST_F(FPDFPPOEmbedderTest, BadIndices) {
452   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
453 
454   FPDF_PAGE page = LoadPage(0);
455   EXPECT_TRUE(page);
456 
457   ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
458   EXPECT_TRUE(output_doc);
459 
460   static constexpr int kBadIndices1[] = {-1};
461   EXPECT_FALSE(FPDF_ImportPagesByIndex(
462       output_doc.get(), document(), kBadIndices1, std::size(kBadIndices1), 0));
463 
464   static constexpr int kBadIndices2[] = {1};
465   EXPECT_FALSE(FPDF_ImportPagesByIndex(
466       output_doc.get(), document(), kBadIndices2, std::size(kBadIndices2), 0));
467 
468   static constexpr int kBadIndices3[] = {-1, 0, 1};
469   EXPECT_FALSE(FPDF_ImportPagesByIndex(
470       output_doc.get(), document(), kBadIndices3, std::size(kBadIndices3), 0));
471 
472   static constexpr int kBadIndices4[] = {42};
473   EXPECT_FALSE(FPDF_ImportPagesByIndex(
474       output_doc.get(), document(), kBadIndices4, std::size(kBadIndices4), 0));
475 
476   UnloadPage(page);
477 }
478 
TEST_F(FPDFPPOEmbedderTest,GoodIndices)479 TEST_F(FPDFPPOEmbedderTest, GoodIndices) {
480   ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
481 
482   FPDF_PAGE page = LoadPage(0);
483   EXPECT_TRUE(page);
484 
485   ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
486   EXPECT_TRUE(output_doc);
487 
488   static constexpr int kGoodIndices1[] = {0, 0, 0, 0};
489   EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
490                                       kGoodIndices1, std::size(kGoodIndices1),
491                                       0));
492   EXPECT_EQ(4, FPDF_GetPageCount(output_doc.get()));
493 
494   static constexpr int kGoodIndices2[] = {0};
495   EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
496                                       kGoodIndices2, std::size(kGoodIndices2),
497                                       0));
498   EXPECT_EQ(5, FPDF_GetPageCount(output_doc.get()));
499 
500   static constexpr int kGoodIndices3[] = {4};
501   EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
502                                       kGoodIndices3, std::size(kGoodIndices3),
503                                       0));
504   EXPECT_EQ(6, FPDF_GetPageCount(output_doc.get()));
505 
506   static constexpr int kGoodIndices4[] = {1, 2, 3};
507   EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
508                                       kGoodIndices4, std::size(kGoodIndices4),
509                                       0));
510   EXPECT_EQ(9, FPDF_GetPageCount(output_doc.get()));
511 
512   // Passing in a nullptr should import all the pages.
513   EXPECT_TRUE(
514       FPDF_ImportPagesByIndex(output_doc.get(), document(), nullptr, 0, 0));
515   EXPECT_EQ(14, FPDF_GetPageCount(output_doc.get()));
516 
517   UnloadPage(page);
518 }
519 
TEST_F(FPDFPPOEmbedderTest,BadRanges)520 TEST_F(FPDFPPOEmbedderTest, BadRanges) {
521   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
522 
523   FPDF_PAGE page = LoadPage(0);
524   EXPECT_TRUE(page);
525 
526   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
527   EXPECT_TRUE(output_doc);
528   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "clams", 0));
529   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "0", 0));
530   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "42", 0));
531   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "1,2", 0));
532   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "1-2", 0));
533   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), ",1", 0));
534   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "1,", 0));
535   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "1-", 0));
536   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "-1", 0));
537   EXPECT_FALSE(FPDF_ImportPages(output_doc, document(), "-,0,,,1-", 0));
538   FPDF_CloseDocument(output_doc);
539 
540   UnloadPage(page);
541 }
542 
TEST_F(FPDFPPOEmbedderTest,GoodRanges)543 TEST_F(FPDFPPOEmbedderTest, GoodRanges) {
544   ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
545 
546   FPDF_PAGE page = LoadPage(0);
547   EXPECT_TRUE(page);
548 
549   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
550   EXPECT_TRUE(output_doc);
551   EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
552   EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "1,1,1,1", 0));
553   EXPECT_EQ(4, FPDF_GetPageCount(output_doc));
554   EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "1-1", 0));
555   EXPECT_EQ(5, FPDF_GetPageCount(output_doc));
556   EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "5-5", 0));
557   EXPECT_EQ(6, FPDF_GetPageCount(output_doc));
558   EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "2-4", 0));
559   EXPECT_EQ(9, FPDF_GetPageCount(output_doc));
560   FPDF_CloseDocument(output_doc);
561 
562   UnloadPage(page);
563 }
564 
TEST_F(FPDFPPOEmbedderTest,BUG_664284)565 TEST_F(FPDFPPOEmbedderTest, BUG_664284) {
566   ASSERT_TRUE(OpenDocument("bug_664284.pdf"));
567 
568   FPDF_PAGE page = LoadPage(0);
569   ASSERT_NE(nullptr, page);
570 
571   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
572   EXPECT_TRUE(output_doc);
573 
574   static constexpr int kIndices[] = {0};
575   EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc, document(), kIndices,
576                                       std::size(kIndices), 0));
577   FPDF_CloseDocument(output_doc);
578 
579   UnloadPage(page);
580 }
581 
TEST_F(FPDFPPOEmbedderTest,BUG_750568)582 TEST_F(FPDFPPOEmbedderTest, BUG_750568) {
583   ASSERT_TRUE(OpenDocument("bug_750568.pdf"));
584   ASSERT_EQ(4, FPDF_GetPageCount(document()));
585 
586   for (size_t i = 0; i < 4; ++i) {
587     FPDF_PAGE page = LoadPage(i);
588     ASSERT_TRUE(page);
589 
590     ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
591     CompareBitmap(bitmap.get(), 200, 200, Bug750568PageHash(i));
592     UnloadPage(page);
593   }
594 
595   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
596   ASSERT_TRUE(output_doc);
597 
598   static constexpr int kIndices[] = {0, 1, 2, 3};
599   EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc, document(), kIndices,
600                                       std::size(kIndices), 0));
601   ASSERT_EQ(4, FPDF_GetPageCount(output_doc));
602   for (size_t i = 0; i < 4; ++i) {
603     FPDF_PAGE page = FPDF_LoadPage(output_doc, i);
604     ASSERT_TRUE(page);
605 
606     ScopedFPDFBitmap bitmap = RenderPage(page);
607     CompareBitmap(bitmap.get(), 200, 200, Bug750568PageHash(i));
608     FPDF_ClosePage(page);
609   }
610   FPDF_CloseDocument(output_doc);
611 }
612 
TEST_F(FPDFPPOEmbedderTest,ImportWithZeroLengthStream)613 TEST_F(FPDFPPOEmbedderTest, ImportWithZeroLengthStream) {
614   ASSERT_TRUE(OpenDocument("zero_length_stream.pdf"));
615   FPDF_PAGE page = LoadPage(0);
616   ASSERT_TRUE(page);
617 
618   ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
619   CompareBitmap(bitmap.get(), 200, 200, pdfium::HelloWorldChecksum());
620   UnloadPage(page);
621 
622   ScopedFPDFDocument new_doc(FPDF_CreateNewDocument());
623   ASSERT_TRUE(new_doc);
624 
625   static constexpr int kIndices[] = {0};
626   EXPECT_TRUE(FPDF_ImportPagesByIndex(new_doc.get(), document(), kIndices,
627                                       std::size(kIndices), 0));
628 
629   EXPECT_EQ(1, FPDF_GetPageCount(new_doc.get()));
630   ScopedFPDFPage new_page(FPDF_LoadPage(new_doc.get(), 0));
631   ASSERT_TRUE(new_page);
632   ScopedFPDFBitmap new_bitmap = RenderPage(new_page.get());
633   CompareBitmap(new_bitmap.get(), 200, 200, pdfium::HelloWorldChecksum());
634 }
635