Disallow empty keys in dictionaries when parsing with CPDF_SyntaxParser.

- Add a new test file and embedder test for this case.
- Add a CHECK() to CPDF_Dictionary::SetFor() to flush out other cases.

Bug: chromium:1191313
Change-Id: I308a29420a5986b078f75ecdf0bcc34d6f483591
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/82790
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index a798b6e..2f77a60 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -210,6 +210,7 @@
 
 CPDF_Object* CPDF_Dictionary::SetFor(const ByteString& key,
                                      RetainPtr<CPDF_Object> pObj) {
+  CHECK(!key.IsEmpty());
   CHECK(!IsLocked());
   if (!pObj) {
     m_Map.erase(key);
diff --git a/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp b/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp
index 814bfa2..873bf50 100644
--- a/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp
+++ b/core/fpdfapi/parser/cpdf_parser_embeddertest.cpp
@@ -80,3 +80,8 @@
   EXPECT_NE(nullptr, page);
   UnloadPage(page);
 }
+
+// crbug.com/1191313
+TEST_F(CPDFParserEmbedderTest, InvalidDictionaryKeys) {
+  ASSERT_TRUE(OpenDocument("bad_dict_keys.pdf"));
+}
diff --git a/core/fpdfapi/parser/cpdf_syntax_parser.cpp b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
index 9538513..47f4f1a 100644
--- a/core/fpdfapi/parser/cpdf_syntax_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_syntax_parser.cpp
@@ -589,9 +589,10 @@
         return nullptr;
       }
 
-      if (!key.IsEmpty()) {
-        ByteString keyNoSlash(key.raw_str() + 1, key.GetLength() - 1);
-        pDict->SetFor(keyNoSlash, std::move(pObj));
+      // `key` has to be "/X" at the minimum.
+      if (key.GetLength() > 1) {
+        ByteString key_no_slash(key.raw_str() + 1, key.GetLength() - 1);
+        pDict->SetFor(key_no_slash, std::move(pObj));
       }
     }
 
diff --git a/testing/resources/bad_dict_keys.in b/testing/resources/bad_dict_keys.in
new file mode 100644
index 0000000..3f53c28
--- /dev/null
+++ b/testing/resources/bad_dict_keys.in
@@ -0,0 +1,23 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [0 0 300 300]
+  /Count 1
+  /Kids [3 0 R]
+  / [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bad_dict_keys.pdf b/testing/resources/bad_dict_keys.pdf
new file mode 100644
index 0000000..b55c434
--- /dev/null
+++ b/testing/resources/bad_dict_keys.pdf
@@ -0,0 +1,33 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /MediaBox [0 0 300 300]
+  /Count 1
+  /Kids [3 0 R]
+  / [3 0 R]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+>>
+endobj
+xref
+0 4
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000169 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 4
+>>
+startxref
+220
+%%EOF