Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: b1a42efa6ce00e8d6cabcf8faff005e734a54190
https://github.com/WebKit/WebKit/commit/b1a42efa6ce00e8d6cabcf8faff005e734a54190
Author: Ryosuke Niwa <[email protected]>
Date: 2026-07-03 (Fri, 03 Jul 2026)
Changed paths:
A LayoutTests/fast/dom/StyleSheet/gc-import-rule-stylesheet-expected.txt
A LayoutTests/fast/dom/StyleSheet/gc-import-rule-stylesheet.html
M Source/WebCore/bindings/js/JSStyleSheetCustom.h
M Source/WebCore/css/CSSImportRule.cpp
M Source/WebCore/css/CSSImportRule.h
M Source/WebCore/css/CSSStyleSheet.cpp
M Source/WebCore/css/CSSStyleSheet.h
M Source/WebCore/css/StyleSheet.h
M Source/WebCore/xml/XSLStyleSheet.h
M Source/WebCore/xml/XSLStyleSheetLibxslt.cpp
M Source/WebKitLegacy/mac/DOM/DOMCSSImportRule.mm
Log Message:
-----------
Data race in JSStyleSheet::visitAdditionalChildren during GC leading to
use-after-free
https://bugs.webkit.org/show_bug.cgi?id=312540
rdar://174207086
Reviewed by Antti Koivisto.
JSStyleSheet::visitAdditionalChildren is called by the JSC garbage collector on
a GC thread.
It calls addWebCoreOpaqueRoot(visitor, wrapped()) with root(StyleSheet*), which
reads
styleSheet->ownerNode() and styleSheet->ownerRule(). Both are WeakPtr member
variables on
CSSStyleSheet or XSLStyleSheet with .get() returning a raw pointer with no ref
count increment,
and the backing WeakPtrImpl can be freed by the main thread between the read
and the subsequent
dereference, causing a heap use-after-free.
The same root(StyleSheet*) function is the convergence point for JSCSSRule's
visitAdditionalChildren and JSCSSStyleDeclaration's visitAdditionalChildren, so
all three GC
visitor paths are affected.
To address this bug, this PR adds a pure virtual opaqueRootForGCThread() to so
root(StyleSheet*)
becomes a single virtual dispatch, eliminating the unsafe inline chain
traversal. This function
then uses a newly added lock (m_opaqueRootLockForGC in CSSStyleSheet and
XSLStyleSheet) to
guard against m_ownerNode being modified while the main thread is mutating it.
In addition, we had a GC correctness bug that @import child stylesheets (which
have m_ownerRule
but no m_ownerNode) would not keep its parent stylesheet's JS wrapper alive
even though it's
accessible via parentStyleSheet property.
To implement these changes and to avoid thread safety issues, this PR changes
the type of
m_ownerNode and m_ownerRule in CSSStyleSheet and XSLStyleSheet from WeakPtr to
CheckedPtr since
WeakPtr loads the pointee address via WeakPtrImpl, which may be concurrently
free'ed in the main
thread while we're accessing it in a GC thread. Note that all owner element
destructors
(HTMLStyleElement, HTMLLinkElement, SVGStyleElement, ProcessingInstruction)
call clearOwnerNode()
before the Node base-class destructor, so the CheckedPtr count reaches zero in
time. Similarly,
learOwnerRule() is called from the CSSImportRule and StyleRuleImport
destructors before
CSSImportRule is freed so CheckedPtr's assertion should not fire.
No new tests for the data race issue itself since there is no reliable way of
testing it.
Test: fast/dom/StyleSheet/gc-import-rule-stylesheet.html
* LayoutTests/fast/dom/StyleSheet/gc-import-rule-stylesheet-expected.txt: Added.
* LayoutTests/fast/dom/StyleSheet/gc-import-rule-stylesheet.html: Added.
* Source/WebCore/bindings/js/JSStyleSheetCustom.h:
(WebCore::root):
* Source/WebCore/css/CSSImportRule.cpp:
(WebCore::CSSImportRule::~CSSImportRule):
* Source/WebCore/css/CSSImportRule.h:
* Source/WebCore/css/CSSStyleSheet.cpp:
(WebCore::CSSStyleSheet::clearOwnerNode):
(WebCore::CSSStyleSheet::opaqueRootForGCThread):
(WebCore::CSSStyleSheet::clearOwnerRule):
* Source/WebCore/css/CSSStyleSheet.h:
* Source/WebCore/css/StyleSheet.h:
* Source/WebCore/xml/XSLStyleSheet.h:
* Source/WebCore/xml/XSLStyleSheetLibxslt.cpp:
(WebCore::XSLStyleSheet::XSLStyleSheet):
(WebCore::XSLStyleSheet::clearOwnerNode):
(WebCore::XSLStyleSheet::opaqueRootForGCThread):
* Source/WebKitLegacy/mac/DOM/DOMCSSImportRule.mm:
(-[DOMCSSImportRule media]):
(-[DOMCSSImportRule styleSheet]):
Originally-landed-as: 305413.691@safari-7624-branch (f41030176464).
rdar://180436921
Canonical link: https://commits.webkit.org/316485@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications