• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 PDFium Authors. All rights reserved.
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 <limits>
6 #include <string>
7 
8 #include "fpdfsdk/src/fpdfview_c_api_test.h"
9 #include "public/fpdfview.h"
10 #include "testing/embedder_test.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
TEST(fpdf,CApiTest)13 TEST(fpdf, CApiTest) {
14   EXPECT_TRUE(CheckPDFiumCApi());
15 }
16 
17 class FPDFViewEmbeddertest : public EmbedderTest {};
18 
TEST_F(FPDFViewEmbeddertest,Document)19 TEST_F(FPDFViewEmbeddertest, Document) {
20   EXPECT_TRUE(OpenDocument("about_blank.pdf"));
21   EXPECT_EQ(1, GetPageCount());
22   EXPECT_EQ(0, GetFirstPageNum());
23 
24   int version;
25   EXPECT_TRUE(FPDF_GetFileVersion(document(), &version));
26   EXPECT_EQ(14, version);
27 
28   EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocPermissions(document()));
29   EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document()));
30 }
31 
TEST_F(FPDFViewEmbeddertest,Page)32 TEST_F(FPDFViewEmbeddertest, Page) {
33   EXPECT_TRUE(OpenDocument("about_blank.pdf"));
34   FPDF_PAGE page = LoadPage(0);
35   EXPECT_NE(nullptr, page);
36   EXPECT_EQ(612.0, FPDF_GetPageWidth(page));
37   EXPECT_EQ(792.0, FPDF_GetPageHeight(page));
38   UnloadPage(page);
39   EXPECT_EQ(nullptr, LoadPage(1));
40 }
41 
TEST_F(FPDFViewEmbeddertest,ViewerRef)42 TEST_F(FPDFViewEmbeddertest, ViewerRef) {
43   EXPECT_TRUE(OpenDocument("about_blank.pdf"));
44   EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document()));
45   EXPECT_EQ(1, FPDF_VIEWERREF_GetNumCopies(document()));
46   EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
47 }
48 
TEST_F(FPDFViewEmbeddertest,NamedDests)49 TEST_F(FPDFViewEmbeddertest, NamedDests) {
50   EXPECT_TRUE(OpenDocument("named_dests.pdf"));
51   long buffer_size;
52   char fixed_buffer[512];
53   FPDF_DEST dest;
54 
55   // Query the size of the first item.
56   buffer_size = 2000000;  // Absurdly large, check not used for this case.
57   dest = FPDF_GetNamedDest(document(), 0, nullptr, &buffer_size);
58   EXPECT_NE(nullptr, dest);
59   EXPECT_EQ(12u, buffer_size);
60 
61   // Try to retrieve the first item with too small a buffer.
62   buffer_size = 10;
63   dest = FPDF_GetNamedDest(document(), 0, fixed_buffer, &buffer_size);
64   EXPECT_NE(nullptr, dest);
65   EXPECT_EQ(-1, buffer_size);
66 
67   // Try to retrieve the first item with correctly sized buffer. Item is
68   // taken from Dests NameTree in named_dests.pdf.
69   buffer_size = 12;
70   dest = FPDF_GetNamedDest(document(), 0, fixed_buffer, &buffer_size);
71   EXPECT_NE(nullptr, dest);
72   EXPECT_EQ(12u, buffer_size);
73   EXPECT_EQ(std::string("F\0i\0r\0s\0t\0\0\0", 12),
74             std::string(fixed_buffer, buffer_size));
75 
76   // Try to retrieve the second item with ample buffer. Item is taken
77   // from Dests NameTree but has a sub-dictionary in named_dests.pdf.
78   buffer_size = sizeof(fixed_buffer);
79   dest = FPDF_GetNamedDest(document(), 1, fixed_buffer, &buffer_size);
80   EXPECT_NE(nullptr, dest);
81   EXPECT_EQ(10u, buffer_size);
82   EXPECT_EQ(std::string("N\0e\0x\0t\0\0\0", 10),
83             std::string(fixed_buffer, buffer_size));
84 
85   // Try to retrieve third item with ample buffer. Item is taken
86   // from Dests NameTree but has a bad sub-dictionary in named_dests.pdf.
87   // in named_dests.pdf).
88   buffer_size = sizeof(fixed_buffer);
89   dest = FPDF_GetNamedDest(document(), 2, fixed_buffer, &buffer_size);
90   EXPECT_EQ(nullptr, dest);
91   EXPECT_EQ(sizeof(fixed_buffer), buffer_size);  // unmodified.
92 
93   // Try to retrieve the forth item with ample buffer. Item is taken
94   // from Dests NameTree but has a vale of the wrong type in named_dests.pdf.
95   buffer_size = sizeof(fixed_buffer);
96   dest = FPDF_GetNamedDest(document(), 3, fixed_buffer, &buffer_size);
97   EXPECT_EQ(nullptr, dest);
98   EXPECT_EQ(sizeof(fixed_buffer), buffer_size);  // unmodified.
99 
100   // Try to retrieve fifth item with ample buffer. Item taken from the
101   // old-style Dests dictionary object in named_dests.pdf.
102   buffer_size = sizeof(fixed_buffer);
103   dest = FPDF_GetNamedDest(document(), 4, fixed_buffer, &buffer_size);
104   EXPECT_NE(nullptr, dest);
105   EXPECT_EQ(30u, buffer_size);
106   EXPECT_EQ(std::string("F\0i\0r\0s\0t\0A\0l\0t\0e\0r\0n\0a\0t\0e\0\0\0", 30),
107             std::string(fixed_buffer, buffer_size));
108 
109   // Try to retrieve sixth item with ample buffer. Item istaken from the
110   // old-style Dests dictionary object but has a sub-dictionary in
111   // named_dests.pdf.
112   buffer_size = sizeof(fixed_buffer);
113   dest = FPDF_GetNamedDest(document(), 5, fixed_buffer, &buffer_size);
114   EXPECT_NE(nullptr, dest);
115   EXPECT_EQ(28u, buffer_size);
116   EXPECT_EQ(std::string("L\0a\0s\0t\0A\0l\0t\0e\0r\0n\0a\0t\0e\0\0\0", 28),
117             std::string(fixed_buffer, buffer_size));
118 
119   // Try to retrieve non-existent item with ample buffer.
120   buffer_size = sizeof(fixed_buffer);
121   dest = FPDF_GetNamedDest(document(), 6, fixed_buffer, &buffer_size);
122   EXPECT_EQ(nullptr, dest);
123   EXPECT_EQ(sizeof(fixed_buffer), buffer_size);  // unmodified.
124 
125   // Try to underflow/overflow the integer index.
126   buffer_size = sizeof(fixed_buffer);
127   dest = FPDF_GetNamedDest(document(), std::numeric_limits<int>::max(),
128                            fixed_buffer, &buffer_size);
129   EXPECT_EQ(nullptr, dest);
130   EXPECT_EQ(sizeof(fixed_buffer), buffer_size);  // unmodified.
131 
132   buffer_size = sizeof(fixed_buffer);
133   dest = FPDF_GetNamedDest(document(), std::numeric_limits<int>::min(),
134                            fixed_buffer, &buffer_size);
135   EXPECT_EQ(nullptr, dest);
136   EXPECT_EQ(sizeof(fixed_buffer), buffer_size);  // unmodified.
137 
138   buffer_size = sizeof(fixed_buffer);
139   dest = FPDF_GetNamedDest(document(), -1, fixed_buffer, &buffer_size);
140   EXPECT_EQ(nullptr, dest);
141   EXPECT_EQ(sizeof(fixed_buffer), buffer_size);  // unmodified.
142 }
143 
TEST_F(FPDFViewEmbeddertest,NamedDestsByName)144 TEST_F(FPDFViewEmbeddertest, NamedDestsByName) {
145   EXPECT_TRUE(OpenDocument("named_dests.pdf"));
146 
147   // Null pointer returns NULL.
148   FPDF_DEST dest = FPDF_GetNamedDestByName(document(), nullptr);
149   EXPECT_EQ(nullptr, dest);
150 
151   // Empty string returns NULL.
152   dest = FPDF_GetNamedDestByName(document(), "");
153   EXPECT_EQ(nullptr, dest);
154 
155   // Item from Dests NameTree.
156   dest = FPDF_GetNamedDestByName(document(), "First");
157   EXPECT_NE(nullptr, dest);
158 
159   long ignore_len = 0;
160   FPDF_DEST dest_by_index =
161       FPDF_GetNamedDest(document(), 0, nullptr, &ignore_len);
162   EXPECT_EQ(dest_by_index, dest);
163 
164   // Item from Dests dictionary.
165   dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
166   EXPECT_NE(nullptr, dest);
167 
168   ignore_len = 0;
169   dest_by_index = FPDF_GetNamedDest(document(), 4, nullptr, &ignore_len);
170   EXPECT_EQ(dest_by_index, dest);
171 
172   // Bad value type for item from Dests NameTree array.
173   dest = FPDF_GetNamedDestByName(document(), "WrongType");
174   EXPECT_EQ(nullptr, dest);
175 
176   // No such destination in either Dest NameTree or dictionary.
177   dest = FPDF_GetNamedDestByName(document(), "Bogus");
178   EXPECT_EQ(nullptr, dest);
179 }
180 
181 // The following tests pass if the document opens without crashing.
TEST_F(FPDFViewEmbeddertest,Crasher_113)182 TEST_F(FPDFViewEmbeddertest, Crasher_113) {
183   EXPECT_TRUE(OpenDocument("bug_113.pdf"));
184 }
185 
TEST_F(FPDFViewEmbeddertest,Crasher_451830)186 TEST_F(FPDFViewEmbeddertest, Crasher_451830) {
187   // Document is damaged and can't be opened.
188   EXPECT_FALSE(OpenDocument("bug_451830.pdf"));
189 }
190 
TEST_F(FPDFViewEmbeddertest,Crasher_452455)191 TEST_F(FPDFViewEmbeddertest, Crasher_452455) {
192   EXPECT_TRUE(OpenDocument("bug_452455.pdf"));
193   FPDF_PAGE page = LoadPage(0);
194   EXPECT_NE(nullptr, page);
195   UnloadPage(page);
196 }
197 
TEST_F(FPDFViewEmbeddertest,Crasher_454695)198 TEST_F(FPDFViewEmbeddertest, Crasher_454695) {
199   // Document is damaged and can't be opened.
200   EXPECT_FALSE(OpenDocument("bug_454695.pdf"));
201 }
202 
TEST_F(FPDFViewEmbeddertest,Crasher_572871)203 TEST_F(FPDFViewEmbeddertest, Crasher_572871) {
204   EXPECT_TRUE(OpenDocument("bug_572871.pdf"));
205 }
206 
207 // The following tests pass if the document opens without infinite looping.
TEST_F(FPDFViewEmbeddertest,Hang_298)208 TEST_F(FPDFViewEmbeddertest, Hang_298) {
209   EXPECT_FALSE(OpenDocument("bug_298.pdf"));
210 }
211 
212 // Test if the document opens without infinite looping.
213 // Previously this test will hang in a loop inside LoadAllCrossRefV4. After
214 // the fix, LoadAllCrossRefV4 will return false after detecting a cross
215 // reference loop. Cross references will be rebuilt successfully.
TEST_F(FPDFViewEmbeddertest,CrossRefV4Loop)216 TEST_F(FPDFViewEmbeddertest, CrossRefV4Loop) {
217   EXPECT_TRUE(OpenDocument("bug_xrefv4_loop.pdf"));
218 }
219 
220 // The test should pass when circular references to ParseIndirectObject will not
221 // cause infinite loop.
TEST_F(FPDFViewEmbeddertest,Hang_343)222 TEST_F(FPDFViewEmbeddertest, Hang_343) {
223   EXPECT_FALSE(OpenDocument("bug_343.pdf"));
224 }
225 
226 // The test should pass when the absence of 'Contents' field in a signature
227 // dictionary will not cause an infinite loop in CPDF_SyntaxParser::GetObject().
TEST_F(FPDFViewEmbeddertest,Hang_344)228 TEST_F(FPDFViewEmbeddertest, Hang_344) {
229   EXPECT_FALSE(OpenDocument("bug_344.pdf"));
230 }