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

Reply via email to