Fix FPDF_GetNamedDest() for old style destinations.

Bug: chromium:1080663
Change-Id: I830fa071ca840b88411c073cb52a67699a3b7286
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/69755
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 4ae33f6..e838e49 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -1105,24 +1105,23 @@
   if (!pRoot)
     return nullptr;
 
+  auto name_tree = CPDF_NameTree::Create(pDoc, "Dests");
+  size_t name_tree_count = name_tree ? name_tree->GetCount() : 0;
   CPDF_Object* pDestObj = nullptr;
   WideString wsName;
-  auto name_tree = CPDF_NameTree::Create(pDoc, "Dests");
-  if (!name_tree)
-    return nullptr;
-
-  size_t count = name_tree->GetCount();
-  if (static_cast<size_t>(index) >= count) {
+  if (static_cast<size_t>(index) >= name_tree_count) {
+    // If |index| is out of bounds, then try to retrieve the Nth old style named
+    // destination. Where N is 0-indexed, with N = index - name_tree_count.
     const CPDF_Dictionary* pDest = pRoot->GetDictFor("Dests");
     if (!pDest)
       return nullptr;
 
-    FX_SAFE_INT32 checked_count = count;
+    FX_SAFE_INT32 checked_count = name_tree_count;
     checked_count += pDest->size();
     if (!checked_count.IsValid() || index >= checked_count.ValueOrDie())
       return nullptr;
 
-    index -= count;
+    index -= name_tree_count;
     int i = 0;
     ByteStringView bsName;
     CPDF_DictionaryLocker locker(pDest);
diff --git a/fpdfsdk/fpdf_view_embeddertest.cpp b/fpdfsdk/fpdf_view_embeddertest.cpp
index 17c2d96..2fe6e39 100644
--- a/fpdfsdk/fpdf_view_embeddertest.cpp
+++ b/fpdfsdk/fpdf_view_embeddertest.cpp
@@ -16,6 +16,7 @@
 #include "public/fpdfview.h"
 #include "testing/embedder_test.h"
 #include "testing/embedder_test_constants.h"
+#include "testing/fx_string_testhelpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/utils/file_util.h"
 #include "testing/utils/path_service.h"
@@ -688,6 +689,9 @@
 }
 
 TEST_F(FPDFViewEmbedderTest, NamedDestsOldStyle) {
+  static constexpr char kFirstAlternate[] = "FirstAlternate";
+  static constexpr char kLastAlternate[] = "LastAlternate";
+
   EXPECT_TRUE(OpenDocument("named_dests_old_style.pdf"));
   EXPECT_EQ(2u, FPDF_CountNamedDests(document()));
 
@@ -697,8 +701,8 @@
   EXPECT_FALSE(FPDF_GetNamedDestByName(document(), "NoSuchName"));
 
   // These should return a valid destination.
-  EXPECT_TRUE(FPDF_GetNamedDestByName(document(), "FirstAlternate"));
-  EXPECT_TRUE(FPDF_GetNamedDestByName(document(), "LastAlternate"));
+  EXPECT_TRUE(FPDF_GetNamedDestByName(document(), kFirstAlternate));
+  EXPECT_TRUE(FPDF_GetNamedDestByName(document(), kLastAlternate));
 
   char buffer[512];
   constexpr long kBufferSize = sizeof(buffer);
@@ -711,13 +715,17 @@
   EXPECT_FALSE(FPDF_GetNamedDest(document(), 2, buffer, &size));
   EXPECT_EQ(kBufferSize, size);
 
-  // TODO(crbug.com/1080663): These should return a valid destination.
+  // These should return a valid destination.
   size = kBufferSize;
-  EXPECT_FALSE(FPDF_GetNamedDest(document(), 0, buffer, &size));
-  EXPECT_EQ(kBufferSize, size);
+  ASSERT_TRUE(FPDF_GetNamedDest(document(), 0, buffer, &size));
+  ASSERT_EQ(static_cast<int>(sizeof(kFirstAlternate) * 2), size);
+  EXPECT_EQ(kFirstAlternate,
+            GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(buffer)));
   size = kBufferSize;
-  EXPECT_FALSE(FPDF_GetNamedDest(document(), 1, buffer, &size));
-  EXPECT_EQ(kBufferSize, size);
+  ASSERT_TRUE(FPDF_GetNamedDest(document(), 1, buffer, &size));
+  ASSERT_EQ(static_cast<int>(sizeof(kLastAlternate) * 2), size);
+  EXPECT_EQ(kLastAlternate,
+            GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(buffer)));
 }
 
 // The following tests pass if the document opens without crashing.