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,