High chrome Memory Corruption 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactMemory corruption in PDF
DescriptionMemory corruption in PDF
ComponentPDF
Bug ClassMemory Corruption
Tracker572237007
Fix commitac3cf1684db0 (pdfium) +124/-54
CISA KEVNot listed
CreditedXinyang Ge (Anthropic), assisted by Claude
Disclosed2026-10-20

Changed Functions

FunctionChangeNotes
if
fpdfsdk/cpdfsdk_formfillenvironment.cpp
modified

Files Changed

  • fpdfsdk/cpdfsdk_formfillenvironment.h
  • fpdfsdk/cpdfsdk_formfillenvironment.cpp
From ac3cf1684db05bd68338acb84e3823e6feb72b5b Mon Sep 17 00:00:00 2001
From: Tom Sepez <[email protected]>
Date: Wed, 14 Oct 2026 11:02:52 -0700
Subject: [PATCH] CHECK on FFE teardown if embedder is inside a callback.

This indicates a misbehaving embedder, so flag it with a CHECK()
while it is still active on the stack.

-- mass rename two hungarian length variables.
-- consistently name AutoRestorer local `restorer`

Bug: 572237007
Change-Id: Ice9212769e4072d76a427379aa13d02fa36be55d
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/160615
Reviewed-by: Lei Zhang <[email protected]>
Commit-Queue: Tom Sepez <[email protected]>
---
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index f6ce8cc..c882bfd 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -75,6 +75,8 @@
 }
 
 CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() {
+  CHECK(!in_active_ffi_callback_);
+  CHECK(!in_passive_ffi_callback_);
   being_destroyed_ = true;
   OnDetachFromDocument();
 
@@ -119,7 +121,7 @@
   CFX_PointF ptA = pFormField->PWLtoFFL(CFX_PointF(rect.left, rect.bottom));
   CFX_PointF ptB = pFormField->PWLtoFFL(CFX_PointF(rect.right, rect.top));
 
-  AutoRestorer<bool> ffi_restorer(&in_passive_ffi_callback_);
+  AutoRestorer<bool> restorer(&in_passive_ffi_callback_);
   in_passive_ffi_callback_ = true;
   info_->FFI_OutputSelectedRect(info_, pPage, ptA.x, ptB.y, ptB.x, ptA.y);
 }
@@ -134,8 +136,10 @@
   return pPage ? GetOrCreatePageView(pPage) : nullptr;
 }
 
-IPDF_Page* CPDFSDK_FormFillEnvironment::GetCurrentPage() const {
+IPDF_Page* CPDFSDK_FormFillEnvironment::GetCurrentPage() {
   if (info_ && info_->FFI_GetCurrentPage) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     return IPDFPageFromFPDFPage(info_->FFI_GetCurrentPage(
         info_, FPDFDocumentFromCPDFDocument(cpdfdoc_.Get())));
   }
@@ -148,19 +152,29 @@
     return WideString();
   }
 
-  int nRequiredLen = info_->FFI_GetLanguage(info_, nullptr, 0);
-  if (nRequiredLen <= 0) {
+  int required_len;
+  {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    required_len = info_->FFI_GetLanguage(info_, nullptr, 0);
+  }
+  if (required_len <= 0) {
     return WideString();
   }
 
-  DataVector<uint8_t> pBuff(nRequiredLen);
-  int nActualLen = info_->FFI_GetLanguage(info_, pBuff.data(), nRequiredLen);
-  if (nActualLen <= 0 || nActualLen > nRequiredLen) {
+  DataVector<uint8_t> pBuff(required_len);
+  int actual_len;
+  {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    actual_len = info_->FFI_GetLanguage(info_, pBuff.data(), required_len);
+  }
+  if (actual_len <= 0 || actual_len > required_len) {
     return WideString();
   }
 
   return WideString::FromUTF16LE(
-      pdfium::span(pBuff).first(static_cast<size_t>(nActualLen)));
+      pdfium::span(pBuff).first(static_cast<size_t>(actual_len)));
 #else   // PDF_ENABLE_XFA
   return WideString();
 #endif  // PDF_ENABLE_XFA
@@ -172,19 +186,29 @@
     return WideString();
   }
 
-  int nRequiredLen = info_->FFI_GetPlatform(info_, nullptr, 0);
-  if (nRequiredLen <= 0) {
+  int required_len;
+  {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    required_len = info_->FFI_GetPlatform(info_, nullptr, 0);
+  }
+  if (required_len <= 0) {
     return WideString();
   }
 
-  DataVector<uint8_t> pBuff(nRequiredLen);
-  int nActualLen = info_->FFI_GetPlatform(info_, pBuff.data(), nRequiredLen);
-  if (nActualLen <= 0 || nActualLen > nRequiredLen) {
+  DataVector<uint8_t> pBuff(required_len);
+  int actual_len;
+  {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    actual_len = info_->FFI_GetPlatform(info_, pBuff.data(), required_len);
+  }
+  if (actual_len <= 0 || actual_len > required_len) {
     return WideString();
   }
 
   return WideString::FromUTF16LE(
-      pdfium::span(pBuff).first(static_cast<size_t>(nActualLen)));
+      pdfium::span(pBuff).first(static_cast<size_t>(actual_len)));
 #else   // PDF_ENABLE_XFA
   return WideString();
 #endif  // PDF_ENABLE_XFA
@@ -242,20 +266,20 @@
     return WideString();
   }
 
-  const int nRequiredLen = js_platform->Field_browse(js_platform, nullptr, 0);
-  if (nRequiredLen <= 0) {
+  const int required_len = js_platform->Field_browse(js_platform, nullptr, 0);
+  if (required_len <= 0) {
     return WideString();
   }
 
-  DataVector<uint8_t> pBuff(nRequiredLen);
-  const int nActualLen =
-      js_platform->Field_browse(js_platform, pBuff.data(), nRequiredLen);
-  if (nActualLen <= 0 || nActualLen > nRequiredLen) {
+  DataVector<uint8_t> pBuff(required_len);
+  const int actual_len =
+      js_platform->Field_browse(js_platform, pBuff.data(), required_len);
+  if (actual_len <= 0 || actual_len > required_len) {
     return WideString();
   }
 
   // Don't include trailing NUL.
-  pBuff.resize(nActualLen - 1);
+  pBuff.resize(actual_len - 1);
 
   // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
   return WideString::FromDefANSI(ByteStringView(pBuff));
@@ -323,21 +347,21 @@
     return WideString();
   }
 
-  const int nRequiredLen =
+  const int required_len =
       js_platform->Doc_getFilePath(js_platform, nullptr, 0);
-  if (nRequiredLen <= 0) {
+  if (required_len <= 0) {
     return WideString();
   }
 
-  DataVector<uint8_t> pBuff(nRequiredLen);
-  const int nActualLen =
-      js_platform->Doc_getFilePath(js_platform, pBuff.data(), nRequiredLen);
-  if (nActualLen <= 0 || nActualLen > nRequiredLen) {
+  DataVector<uint8_t> pBuff(required_len);
+  const int actual_len =
+      js_platform->Doc_getFilePath(js_platform, pBuff.data(), required_len);
+  if (actual_len <= 0 || actual_len > required_len) {
     return WideString();
   }
 
   // Don't include trailing NUL.
-  pBuff.resize(nActualLen - 1);
+  pBuff.resize(actual_len - 1);
 
   // Use FromDefANSI() per "local encoding" comment in fpdf_formfill.h.
   return WideString::FromDefANSI(ByteStringView(pBuff));
@@ -378,7 +402,7 @@
 void CPDFSDK_FormFillEnvironment::Invalidate(IPDF_Page* page,
                                              const FX_RECT& rect) {
   if (info_ && info_->FFI_Invalidate) {
-    AutoRestorer<bool> ffi_restorer(&in_passive_ffi_callback_);
+    AutoRestorer<bool> restorer(&in_passive_ffi_callback_);
     in_passive_ffi_callback_ = true;
     info_->FFI_Invalidate(info_, FPDFPageFromIPDFPage(page), rect.left,
                           rect.top, rect.right, rect.bottom);
@@ -388,7 +412,7 @@
 void CPDFSDK_FormFillEnvironment::SetCursor(
     IPWL_FillerNotify::CursorStyle nCursorType) {
   if (info_ && info_->FFI_SetCursor) {
-    AutoRestorer<bool> ffi_restorer(&in_passive_ffi_callback_);
+    AutoRestorer<bool> restorer(&in_passive_ffi_callback_);
     in_passive_ffi_callback_ = true;
     info_->FFI_SetCursor(info_, static_cast<int>(nCursorType));
   }
@@ -397,6 +421,8 @@
 int CPDFSDK_FormFillEnvironment::SetTimer(int uElapse,
                                           TimerCallback lpTimerFunc) {
   if (info_ && info_->FFI_SetTimer) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     return info_->FFI_SetTimer(info_, uElapse, lpTimerFunc);
   }
   return CFX_Timer::HandlerIface::kInvalidTimerID;
@@ -404,13 +430,15 @@
 
 void CPDFSDK_FormFillEnvironment::KillTimer(int nTimerID) {
   if (info_ && info_->FFI_KillTimer) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     info_->FFI_KillTimer(info_, nTimerID);
   }
 }
 
 void CPDFSDK_FormFillEnvironment::OnChange() {
   if (info_ && info_->FFI_OnChange) {
-    AutoRestorer<bool> ffi_restorer(&in_passive_ffi_callback_);
+    AutoRestorer<bool> restorer(&in_passive_ffi_callback_);
     in_passive_ffi_callback_ = true;
     info_->FFI_OnChange(info_);
   }
@@ -419,6 +447,8 @@
 void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(
     const ByteString& namedAction) {
   if (info_ && info_->FFI_ExecuteNamedAction) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     info_->FFI_ExecuteNamedAction(info_, namedAction.c_str());
   }
 }
@@ -434,7 +464,7 @@
     size_t nCharacters = text.GetLength();
     ByteString bsUTFText = text.ToUTF16LE();
     auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
-    AutoRestorer<bool> ffi_restorer(&in_passive_ffi_callback_);
+    AutoRestorer<bool> restorer(&in_passive_ffi_callback_);
     in_passive_ffi_callback_ = true;
     info_->FFI_SetTextFieldFocus(
         info_, pBuffer, pdfium::checked_cast<FPDF_DWORD>(nCharacters), bFocus);
@@ -471,14 +501,16 @@
   if (!info_) {
     return;
   }
-
   if (info_->version >= 2 && info_->FFI_DoURIActionWithKeyboardModifier) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     info_->FFI_DoURIActionWithKeyboardModifier(info_, bsURI.c_str(),
                                                modifiers.UncheckedValue());
     return;
   }
-
   if (info_->FFI_DoURIAction) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     info_->FFI_DoURIAction(info_, bsURI.c_str());
   }
 }
@@ -487,6 +519,8 @@
                                                int zoomMode,
                                                pdfium::span<float> fPosArray) {
   if (info_ && info_->FFI_DoGoToAction) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     info_->FFI_DoGoToAction(info_, nPageIndex, zoomMode, fPosArray.data(),
                             fxcrt::CollectionSize<int>(fPosArray));
   }
@@ -504,17 +538,19 @@
                                                double right,
                                                double bottom) {
   if (info_ && info_->version >= 2 && info_->FFI_DisplayCaret) {
-    AutoRestorer<bool> ffi_restorer(&in_passive_ffi_callback_);
+    AutoRestorer<bool> restorer(&in_passive_ffi_callback_);
     in_passive_ffi_callback_ = true;
     info_->FFI_DisplayCaret(info_, FPDFPageFromIPDFPage(page), bVisible, left,
                             top, right, bottom);
   }
 }
 
-int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex() const {
+int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex() {
   if (!info_ || info_->version < 2 || !info_->FFI_GetCurrentPageIndex) {
     return -1;
   }
+  AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+  in_active_ffi_callback_ = true;
   return info_->FFI_GetCurrentPageIndex(
       info_, FPDFDocumentFromCPDFDocument(cpdfdoc_.Get()));
 }
@@ -523,6 +559,8 @@
   if (!info_ || info_->version < 2 || !info_->FFI_SetCurrentPage) {
     return;
   }
+  AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+  in_active_ffi_callback_ = true;
   info_->FFI_SetCurrentPage(info_, FPDFDocumentFromCPDFDocument(cpdfdoc_.Get()),
                             iCurPage);
 }
@@ -533,6 +571,8 @@
   }
 
   ByteString bsTo = wsURL.ToUTF16LE();
+  AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+  in_active_ffi_callback_ = true;
   info_->FFI_GotoURL(info_, FPDFDocumentFromCPDFDocument(cpdfdoc_.Get()),
                      AsFPDFWideString(&bsTo));
 }
@@ -547,8 +587,12 @@
   double top;
   double right;
   double bottom;
-  info_->FFI_GetPageViewRect(info_, FPDFPageFromIPDFPage(page), &left, &top,
-                             &right, &bottom);
+  {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    info_->FFI_GetPageViewRect(info_, FPDFPageFromIPDFPage(page), &left, &top,
+                               &right, &bottom);
+  }
 
   rect.left = static_cast<float>(left);
   rect.top = static_cast<float>(top);
@@ -560,9 +604,13 @@
 bool CPDFSDK_FormFillEnvironment::PopupMenu(IPDF_Page* page,
                                             int menuFlag,
                                             const CFX_PointF& pt) {
-  return info_ && info_->version >= 2 && info_->FFI_PopupMenu &&
-         info_->FFI_PopupMenu(info_, FPDFPageFromIPDFPage(page), nullptr,
-                              menuFlag, pt.x, pt.y);
+  if (info_ && info_->version >= 2 && info_->FFI_PopupMenu) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    return info_->FFI_PopupMenu(info_, FPDFPageFromIPDFPage(page), nullptr,
+                                menuFlag, pt.x, pt.y);
+  }
+  return false;
 }
 
 void CPDFSDK_FormFillEnvironment::EmailTo(FPDF_FILEHANDLER* fileHandler,
@@ -572,6 +620,8 @@
                                           FPDF_WIDESTRING pBcc,
                                           FPDF_WIDESTRING pMsg) {
   if (info_ && info_->version >= 2 && info_->FFI_EmailTo) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     info_->FFI_EmailTo(info_, fileHandler, pTo, pSubject, pCC, pBcc, pMsg);
   }
 }
@@ -580,6 +630,8 @@
                                            int fileFlag,
                                            FPDF_WIDESTRING uploadTo) {
   if (info_ && info_->version >= 2 && info_->FFI_UploadTo) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     info_->FFI_UploadTo(info_, fileHandler, fileFlag, uploadTo);
   }
 }
@@ -588,6 +640,8 @@
                                                         FPDF_WIDESTRING wsURL,
                                                         const char* mode) {
   if (info_ && info_->version >= 2 && info_->FFI_OpenFile) {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
     return info_->FFI_OpenFile(info_, fileType, wsURL, mode);
   }
   return nullptr;
@@ -600,8 +654,13 @@
   }
 
   ByteString bstrURL = url.ToUTF16LE();
-  FPDF_FILEHANDLER* file_handler =
-      info_->FFI_DownloadFromURL(info_, AsFPDFWideString(&bstrURL));
+  FPDF_FILEHANDLER* file_handler;
+  {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    file_handler =
+        info_->FFI_DownloadFromURL(info_, AsFPDFWideString(&bstrURL));
+  }
   if (!file_handler) {
     return nullptr;
   }
@@ -627,10 +686,14 @@
 
   FPDF_BSTR response;
   FPDF_BStr_Init(&response);
-  info_->FFI_PostRequestURL(
-      info_, AsFPDFWideString(&bsURL), AsFPDFWideString(&bsData),
-      AsFPDFWideString(&bsContentType), AsFPDFWideString(&bsEncode),
-      AsFPDFWideString(&bsHeader), &response);
+  {
+    AutoRestorer<bool> restorer(&in_active_ffi_callback_);
+    in_active_ffi_callback_ = true;
+    info_->FFI_PostRequestURL(
+        info_, AsFPDFWideString(&bsURL), AsFPDFWideString(&bsData),
+        AsFPDFWideString(&bsContentType), AsFPDFWideString(&bsEncode),
+        AsFPDFWideString(&bsHeader), &response);
... (file diff truncated)
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.