• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 "core/fpdfapi/parser/fpdf_parser_utility.h"
6 
7 #include <memory>
8 
9 #include "core/fpdfapi/page/cpdf_pagemodule.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_reference.h"
14 #include "core/fpdfapi/parser/cpdf_string.h"
15 #include "core/fpdfapi/parser/cpdf_test_document.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
TEST(ParserUtilityTest,NameDecode)18 TEST(ParserUtilityTest, NameDecode) {
19   EXPECT_EQ("", PDF_NameDecode(""));
20   EXPECT_EQ("A", PDF_NameDecode("A"));
21   EXPECT_EQ("#", PDF_NameDecode("#"));
22   EXPECT_EQ("#4", PDF_NameDecode("#4"));
23   EXPECT_EQ("A", PDF_NameDecode("#41"));
24   EXPECT_EQ("A1", PDF_NameDecode("#411"));
25 }
26 
TEST(ParserUtilityTest,NameEncode)27 TEST(ParserUtilityTest, NameEncode) {
28   EXPECT_EQ("", PDF_NameEncode(""));
29   EXPECT_EQ("A", PDF_NameEncode("A"));
30   EXPECT_EQ("#23", PDF_NameEncode("#"));
31   EXPECT_EQ("#20", PDF_NameEncode(" "));
32   EXPECT_EQ("!@#23$#25^&*#28#29#3C#3E#5B#5D", PDF_NameEncode("!@#$%^&*()<>[]"));
33   EXPECT_EQ("#C2", PDF_NameEncode("\xc2"));
34   EXPECT_EQ("f#C2#A5", PDF_NameEncode("f\xc2\xa5"));
35 }
36 
TEST(ParserUtilityTest,ValidateDictType)37 TEST(ParserUtilityTest, ValidateDictType) {
38   auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
39 
40   // No type.
41   EXPECT_FALSE(ValidateDictType(dict.Get(), "foo"));
42   EXPECT_FALSE(ValidateDictType(dict.Get(), "bar"));
43 
44   // Add the wrong object type.
45   dict->SetNewFor<CPDF_String>("Type", L"foo");
46   EXPECT_FALSE(ValidateDictType(dict.Get(), "foo"));
47   EXPECT_FALSE(ValidateDictType(dict.Get(), "bar"));
48 
49   // Add the correct object type.
50   dict->SetNewFor<CPDF_Name>("Type", "foo");
51   EXPECT_TRUE(ValidateDictType(dict.Get(), "foo"));
52   EXPECT_FALSE(ValidateDictType(dict.Get(), "bar"));
53 }
54 
TEST(ParserUtilityTest,ValidateDictAllResourcesOfType)55 TEST(ParserUtilityTest, ValidateDictAllResourcesOfType) {
56   CPDF_PageModule::Create();
57 
58   {
59     // Direct dictionary.
60     auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
61 
62     // Empty dict is ok.
63     EXPECT_TRUE(ValidateDictAllResourcesOfType(dict.Get(), "foo"));
64     EXPECT_TRUE(ValidateDictAllResourcesOfType(dict.Get(), "bar"));
65 
66     // nullptr is not.
67     EXPECT_FALSE(ValidateDictAllResourcesOfType(nullptr, "foo"));
68     EXPECT_FALSE(ValidateDictAllResourcesOfType(nullptr, "bar"));
69 
70     // Add two correct dictionary entries and one string entry.
71     auto new_dict = dict->SetNewFor<CPDF_Dictionary>("f1");
72     new_dict->SetNewFor<CPDF_Name>("Type", "foo");
73     new_dict = dict->SetNewFor<CPDF_Dictionary>("f2");
74     new_dict->SetNewFor<CPDF_Name>("Type", "foo");
75     dict->SetNewFor<CPDF_String>("f3", L"foo");
76     EXPECT_FALSE(ValidateDictAllResourcesOfType(dict.Get(), "foo"));
77     EXPECT_FALSE(ValidateDictAllResourcesOfType(dict.Get(), "bar"));
78 
79     // Change the string entry to a dictionary, but with the wrong /Type.
80     new_dict = dict->SetNewFor<CPDF_Dictionary>("f3");
81     new_dict->SetNewFor<CPDF_Name>("Type", "bar");
82     EXPECT_FALSE(ValidateDictAllResourcesOfType(dict.Get(), "foo"));
83     EXPECT_FALSE(ValidateDictAllResourcesOfType(dict.Get(), "bar"));
84 
85     // Change the /Type to match.
86     new_dict->SetNewFor<CPDF_Name>("Type", "foo");
87     EXPECT_TRUE(ValidateDictAllResourcesOfType(dict.Get(), "foo"));
88     EXPECT_FALSE(ValidateDictAllResourcesOfType(dict.Get(), "bar"));
89   }
90 
91   {
92     // Indirect dictionary.
93     auto doc = std::make_unique<CPDF_TestDocument>();
94     auto dict = doc->New<CPDF_Dictionary>();
95 
96     // Add a correct dictionary entry.
97     auto new_dict = doc->NewIndirect<CPDF_Dictionary>();
98     new_dict->SetNewFor<CPDF_Name>("Type", "foo");
99     dict->SetNewFor<CPDF_Reference>("f1", doc.get(), new_dict->GetObjNum());
100 
101     EXPECT_TRUE(ValidateDictAllResourcesOfType(dict.Get(), "foo"));
102     EXPECT_FALSE(ValidateDictAllResourcesOfType(dict.Get(), "bar"));
103   }
104 
105   CPDF_PageModule::Destroy();
106 }
107 
TEST(ParserUtilityTest,ValidateDictOptionalType)108 TEST(ParserUtilityTest, ValidateDictOptionalType) {
109   auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
110 
111   // No type is ok.
112   EXPECT_TRUE(ValidateDictOptionalType(dict.Get(), "foo"));
113   EXPECT_TRUE(ValidateDictOptionalType(dict.Get(), "bar"));
114 
115   // Add the wrong object type.
116   dict->SetNewFor<CPDF_String>("Type", L"foo");
117   EXPECT_FALSE(ValidateDictOptionalType(dict.Get(), "foo"));
118   EXPECT_FALSE(ValidateDictOptionalType(dict.Get(), "bar"));
119 
120   // Add the correct object type.
121   dict->SetNewFor<CPDF_Name>("Type", "foo");
122   EXPECT_TRUE(ValidateDictOptionalType(dict.Get(), "foo"));
123   EXPECT_FALSE(ValidateDictOptionalType(dict.Get(), "bar"));
124 }
125