Add CPDF_Dictionary::GetNameFor().
Add a method to make it easy to check a value in a dictionary is a name.
Many parts of the PDF spec require names, but too often PDFium is just
calling CPDF_Dictionary::GetStringFor(), which is not strict enough.
- Document the difference in cpdf_dictionary.h.
- Add unit test to show the difference.
- Use GetStringFor() to simplify some existing name checks.
- Add some missing curly braces per style guide.
Change-Id: Ife9569f6049c07224e1c8826c442ee178650c923
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70852
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
index 7011f8e..9a7eddc 100644
--- a/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_cross_ref_avail.cpp
@@ -8,7 +8,6 @@
#include <memory>
#include "core/fpdfapi/parser/cpdf_dictionary.h"
-#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_read_validator.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_syntax_parser.h"
@@ -186,12 +185,12 @@
return false;
}
- const CPDF_Name* type_name = ToName(trailer->GetObjectFor(kTypeFieldKey));
- if (type_name && type_name->GetString() == kXRefKeyword) {
+ if (trailer->GetNameFor(kTypeFieldKey) == kXRefKeyword) {
const int32_t xrefpos = trailer->GetIntegerFor(kPrevCrossRefFieldKey);
if (xrefpos &&
- pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(xrefpos))
+ pdfium::base::IsValueInRangeForNumericType<FX_FILESIZE>(xrefpos)) {
AddCrossRefForCheck(static_cast<FX_FILESIZE>(xrefpos));
+ }
}
// Goto check next crossref
current_state_ = State::kCrossRefCheck;
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index fc0981d..7dc2bb1 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -121,6 +121,11 @@
return p ? p->GetUnicodeText() : WideString();
}
+ByteString CPDF_Dictionary::GetNameFor(const ByteString& key) const {
+ const CPDF_Name* p = ToName(GetObjectFor(key));
+ return p ? p->GetString() : ByteString();
+}
+
bool CPDF_Dictionary::GetBooleanFor(const ByteString& key,
bool bDefault) const {
const CPDF_Object* p = GetObjectFor(key);
diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h
index 57796d7..8cf00e0 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.h
+++ b/core/fpdfapi/parser/cpdf_dictionary.h
@@ -48,10 +48,19 @@
CPDF_Object* GetObjectFor(const ByteString& key);
const CPDF_Object* GetDirectObjectFor(const ByteString& key) const;
CPDF_Object* GetDirectObjectFor(const ByteString& key);
+
+ // These will return the string representation of the object specified by
+ // |key|, for any object type that has a string representation.
ByteString GetStringFor(const ByteString& key) const;
ByteString GetStringFor(const ByteString& key,
const ByteString& default_str) const;
WideString GetUnicodeTextFor(const ByteString& key) const;
+
+ // This will only return the string representation of a name object specified
+ // by |key|. Useful when the PDF spec requires the value to be an object of
+ // type name. i.e. /Foo and not (Foo).
+ ByteString GetNameFor(const ByteString& key) const;
+
bool GetBooleanFor(const ByteString& key, bool bDefault) const;
int GetIntegerFor(const ByteString& key) const;
int GetIntegerFor(const ByteString& key, int default_int) const;
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index 2171c74..8e6d3d2 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -115,11 +115,7 @@
// static
bool CPDF_Document::IsValidPageObject(const CPDF_Object* obj) {
const CPDF_Dictionary* dict = ToDictionary(obj);
- if (!dict)
- return false;
-
- const CPDF_Name* name = ToName(dict->GetObjectFor("Type"));
- return name && name->GetString() == "Page";
+ return dict && dict->GetNameFor("Type") == "Page";
}
RetainPtr<CPDF_Object> CPDF_Document::ParseIndirectObject(uint32_t objnum) {
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index eb82036..0e8da80 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -271,6 +271,23 @@
EXPECT_TRUE(Equal(indirect_obj_results[i], m_RefObjs[i]->GetDict()));
}
+TEST_F(PDFObjectsTest, GetNameFor) {
+ m_DictObj->SetNewFor<CPDF_String>("string", "ium", false);
+ m_DictObj->SetNewFor<CPDF_Name>("name", "Pdf");
+
+ EXPECT_STREQ("", m_DictObj->GetNameFor("invalid").c_str());
+ EXPECT_STREQ("", m_DictObj->GetNameFor("bool").c_str());
+ EXPECT_STREQ("", m_DictObj->GetNameFor("num").c_str());
+ EXPECT_STREQ("", m_DictObj->GetNameFor("string").c_str());
+ EXPECT_STREQ("Pdf", m_DictObj->GetNameFor("name").c_str());
+
+ EXPECT_STREQ("", m_DictObj->GetStringFor("invalid").c_str());
+ EXPECT_STREQ("false", m_DictObj->GetStringFor("bool").c_str());
+ EXPECT_STREQ("0.23", m_DictObj->GetStringFor("num").c_str());
+ EXPECT_STREQ("ium", m_DictObj->GetStringFor("string").c_str());
+ EXPECT_STREQ("Pdf", m_DictObj->GetStringFor("name").c_str());
+}
+
TEST_F(PDFObjectsTest, GetArray) {
const CPDF_Array* const direct_obj_results[] = {
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
diff --git a/core/fpdfapi/parser/fpdf_parser_utility.cpp b/core/fpdfapi/parser/fpdf_parser_utility.cpp
index af58e8d..e6a7f61 100644
--- a/core/fpdfapi/parser/fpdf_parser_utility.cpp
+++ b/core/fpdfapi/parser/fpdf_parser_utility.cpp
@@ -9,7 +9,6 @@
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_boolean.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
-#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
@@ -164,10 +163,8 @@
}
bool ValidateDictType(const CPDF_Dictionary* dict, const ByteString& type) {
- ASSERT(dict);
ASSERT(!type.IsEmpty());
- const CPDF_Name* name_obj = ToName(dict->GetObjectFor("Type"));
- return name_obj && name_obj->GetString() == type;
+ return dict->GetNameFor("Type") == type;
}
bool ValidateDictAllResourcesOfType(const CPDF_Dictionary* dict,