Chrome · Frame
CVE-2026-17971
Logic Error in Frame
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.html |
modified |
Files Changed
third_party/blink/renderer/core/frame/local_frame.ccthird_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.htmlthird_party/blink/web_tests/printing/resources/remove-iframe-beforeprint-crash-child.html
Patch
From b93fe74ce13916f57acd73148d2ec8e5aa7b7ed0 Mon Sep 17 00:00:00 2001 From: Mason Freed <[email protected]> Date: Tue, 09 Jun 2026 09:37:38 -0700 Subject: [PATCH] Null-check GetFrameScheduler() in LocalFrame::SetHadUserInteraction() Calling SetHadUserInteraction() on a frame that gets detached during unwinding or inside synchronous print events can encounter a null FrameScheduler. This adds a check for GetFrameScheduler() before calling SetHadUserActivation(). Fixed: 518815075 Change-Id: I783b20ebcb682c648fd907d170895b787dbe40d7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7905327 Reviewed-by: Joey Arhar <[email protected]> Commit-Queue: Mason Freed <[email protected]> Auto-Submit: Mason Freed <[email protected]> Cr-Commit-Position: refs/heads/main@{#1644040} --- diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 20ff202..7b016194 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc @@ -2927,7 +2927,9 @@ DomWindow()->closewatcher_stack()->SetHadUserInteraction( had_user_interaction); - GetFrameScheduler()->SetHadUserActivation(had_user_interaction); + if (auto* scheduler = GetFrameScheduler()) { + scheduler->SetHadUserActivation(had_user_interaction); + } } namespace { diff --git a/third_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.html b/third_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.html new file mode 100644 index 0000000..3a612ae --- /dev/null +++ b/third_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" href="mailto:[email protected]"> +<link rel="help" href="https://crbug.com/518815075"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../resources/testdriver.js"></script> +<script src="../resources/testdriver-actions.js"></script> +<script src="../resources/testdriver-vendor.js"></script> + +<!-- This test passes if it doesn't crash. --> + +<iframe src="resources/remove-iframe-beforeprint-crash-child.html"></iframe> + +<script> +async_test(t => { + window.finishTest = t.step_func_done(() => {}); + + window.addEventListener('beforeprint', t.step_func(() => { + let f = document.querySelector('iframe'); + if (f) { + f.remove(); + } + }), { once: true }); +}, "This is a crash test and it passes if it doesn't crash."); +</script> + diff --git a/third_party/blink/web_tests/printing/resources/remove-iframe-beforeprint-crash-child.html b/third_party/blink/web_tests/printing/resources/remove-iframe-beforeprint-crash-child.html new file mode 100644 index 0000000..f682ec1 --- /dev/null +++ b/third_party/blink/web_tests/printing/resources/remove-iframe-beforeprint-crash-child.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" href="mailto:[email protected]"> +<link rel="help" href="https://crbug.com/518815075"> + +<body style="margin:0"> + +<div id="clicktarget">CLICK HERE</div> + +<form id="login" action="/login" method="post" + style="position:absolute;left:0;top:0;opacity:0.01;pointer-events:none"> + <input type="text" id="username" name="username" autocomplete="username"> + <input type="password" id="password" name="password" autocomplete="current-password"> + <input type="submit" value="go"> +</form> + +<script> +let armed = false; + +function trigger() { + if (!armed) return; + armed = false; + top.print(); + top.finishTest(); +} + +username.addEventListener('input', trigger); +username.addEventListener('change', trigger); +password.addEventListener('input', trigger); +clicktarget.addEventListener('mousedown', trigger); + +window.addEventListener('load', () => { + setTimeout(() => { + armed = true; + new top.test_driver.Actions() + .pointerMove(0, 0, {origin: clicktarget}) + .pointerDown() + .pointerUp() + .send(); + }, 0); +}); +</script> +</body>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.html b/third_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.html new file mode 100644 index 0000000..3a612ae --- /dev/null +++ b/third_party/blink/web_tests/printing/remove-iframe-beforeprint-crash.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" href="mailto:[email protected]"> +<link rel="help" href="https://crbug.com/518815075"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../resources/testdriver.js"></script> +<script src="../resources/testdriver-actions.js"></script> +<script src="../resources/testdriver-vendor.js"></script> + +<!-- This test passes if it doesn't crash. --> + +<iframe src="resources/remove-iframe-beforeprint-crash-child.html"></iframe> + +<script> +async_test(t => { + window.finishTest = t.step_func_done(() => {}); + + window.addEventListener('beforeprint', t.step_func(() => { + let f = document.querySelector('iframe'); + if (f) { + f.remove(); + } + }), { once: true }); +}, "This is a crash test and it passes if it doesn't crash."); +</script> + diff --git a/third_party/blink/web_tests/printing/resources/remove-iframe-beforeprint-crash-child.html b/third_party/blink/web_tests/printing/resources/remove-iframe-beforeprint-crash-child.html new file mode 100644 index 0000000..f682ec1 --- /dev/null +++ b/third_party/blink/web_tests/printing/resources/remove-iframe-beforeprint-crash-child.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" href="mailto:[email protected]"> +<link rel="help" href="https://crbug.com/518815075"> + +<body style="margin:0"> + +<div id="clicktarget">CLICK HERE</div> + +<form id="login" action="/login" method="post" + style="position:absolute;left:0;top:0;opacity:0.01;pointer-events:none"> + <input type="text" id="username" name="username" autocomplete="username"> + <input type="password" id="password" name="password" autocomplete="current-password"> + <input type="submit" value="go"> +</form> + +<script> +let armed = false; + +function trigger() { + if (!armed) return; + armed = false; + top.print(); + top.finishTest(); +} + +username.addEventListener('input', trigger); +username.addEventListener('change', trigger); +password.addEventListener('input', trigger); +clicktarget.addEventListener('mousedown', trigger); + +window.addEventListener('load', () => { + setTimeout(() => { + armed = true; + new top.test_driver.Actions() + .pointerMove(0, 0, {origin: clicktarget}) + .pointerDown() + .pointerUp() + .send(); + }, 0); +}); +</script> +</body>
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.
References
On This Page