Fix a bad array index calculation in CFDE_TextOut::ReloadLinePiece().

ReloadLinePiece() should not assume the pieces being reloaded are
contiguous and in-order.

Bug: chromium:953881
Change-Id: I0677a79f4424be24a4473bba96e5192d2e726b3f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/95190
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Nigi <nigi@chromium.org>
diff --git a/xfa/fde/cfde_textout.cpp b/xfa/fde/cfde_textout.cpp
index 0b9441a..7debf25 100644
--- a/xfa/fde/cfde_textout.cpp
+++ b/xfa/fde/cfde_textout.cpp
@@ -466,13 +466,13 @@
   CFGAS_Char::BreakType break_status = CFGAS_Char::BreakType::kNone;
   for (size_t piece_index = 0; piece_index < piece_count; ++piece_index) {
     const Piece* piece = line->GetPieceAtIndex(piece_index);
-    if (piece_index == 0) {
-      start_char = piece->start_char;
+    if (piece_index == 0)
       m_fLinePos = piece->bounds.top;
-    }
-    size_t end = start_char + piece->char_count;
-    for (size_t start = start_char; start < end; ++start) {
-      break_status = m_pTxtBreak->AppendChar(text_span[start]);
+
+    start_char = piece->start_char;
+    const size_t end = piece->start_char + piece->char_count;
+    for (size_t char_index = start_char; char_index < end; ++char_index) {
+      break_status = m_pTxtBreak->AppendChar(text_span[char_index]);
       if (!CFX_BreakTypeNoneOrPiece(break_status))
         RetrievePieces(break_status, true, rect, &start_char, &piece_widths);
     }
diff --git a/xfa/fde/cfde_textout_unittest.cpp b/xfa/fde/cfde_textout_unittest.cpp
index 57e60a5..b83cbfd 100644
--- a/xfa/fde/cfde_textout_unittest.cpp
+++ b/xfa/fde/cfde_textout_unittest.cpp
@@ -115,10 +115,40 @@
         "101745f76351fd5d916bf3817b71563c";
     return kEmptyLargeBitmapChecksum;
   }
+
+  const char* GetLargeTextBlobChecksum() {
+#if defined(_SKIA_SUPPORT_)
+    static const char kExpectedChecksum[] = "6181929583fd7651169306852397806f";
+#else
+    static const char kExpectedChecksum[] = "268b71a8660b51e31c6bf30fc7ff1e08";
+#endif
+    return kExpectedChecksum;
+  }
 };
 
-// See crbug.com/1342078
-TEST_F(CFDETextOutLargeBitmapTest, DrawLogicText) {
+TEST_F(CFDETextOutLargeBitmapTest, DrawLogicTextBug953881) {
+  FDE_TextStyle styles;
+  styles.single_line_ = true;
+  text_out().SetStyles(styles);
+  text_out().SetAlignment(FDE_TextAlignment::kCenterLeft);
+  text_out().SetFontSize(10.0f);
+
+  static const wchar_t kText[] =
+      L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
+      L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSssssssssss"
+      L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
+      L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
+      L"sssssssssssssssssssssssssssssssssssssssssssssssssnnnnnnnnnnn"
+      "\xfeba"
+      L"Sssssssssssssssssss"
+      "\xfeba"
+      L"iiiiisssss";
+  text_out().DrawLogicText(device(), WideString(kText),
+                           CFX_RectF(3, 3, 2048, 10));
+  EXPECT_STREQ(GetLargeTextBlobChecksum(), GetBitmapChecksum().c_str());
+}
+
+TEST_F(CFDETextOutLargeBitmapTest, DrawLogicTextBug1342078) {
   FDE_TextStyle styles;
   styles.single_line_ = true;
   text_out().SetStyles(styles);
@@ -137,11 +167,6 @@
       L"iiiiiiiiiisssss";
   text_out().DrawLogicText(device(), WideString(kText),
                            CFX_RectF(3, 3, 2048, 10));
-#if defined(_SKIA_SUPPORT_)
-  static const char kExpectedChecksum[] = "6181929583fd7651169306852397806f";
-#else
-  static const char kExpectedChecksum[] = "268b71a8660b51e31c6bf30fc7ff1e08";
-#endif
-  EXPECT_STREQ(kExpectedChecksum, GetBitmapChecksum().c_str());
+  EXPECT_STREQ(GetLargeTextBlobChecksum(), GetBitmapChecksum().c_str());
 }
 #endif  // !BUILDFLAG(IS_WIN)