← WebKit — 2026-W39

fea825bf5734f0bbf321d0b90917526f26cd2eb2  [WebKit Editing] Shared-Memory Double-Fetch and Unvalidated Operands in toWebMultiRepresentationHEICAttachment (CTEmojiImageAsset)).

severity medium class InputValidation confidence 0.5 signal score 12.06 Source/WebCore/editing
Primitive: non-finite FloatSize from untrusted IPC reaching CoreText emoji strike (CTEmojiImageStrike alignmentInset)
Triage note: Adds an IPC [Validator=WebCore::isValidMultiRepresentationHEICImageSize] enforcing std::isfinite on the deserialized MultiRepresentationHEICAttachmentSingleImage size, plus isValid()/null-image guards and a BEGIN_BLOCK_OBJC_EXCEPTIONS-wrapped ShareableBitmap snapshot path, and fixes a wrong-variable (identifier vs credit) provenance check. Genuine untrusted-IPC input-validation hardening for data that feeds CoreText, but no concrete memory-safety primitive demonstrated.
Structural signals: smartptr_member_added (+6.47), null_guard (+2.59), msg_soft (+1.0), area:Source/WebCore/editing (+2.0)

Commit message

[WebKit Editing] Shared-Memory Double-Fetch and Unvalidated Operands in toWebMultiRepresentationHEICAttachment (CTEmojiImageAsset)).
https://bugs.webkit.org/show_bug.cgi?id=324577
rdar://183073388

Reviewed by Pascoe and Aditya Keerthi.

Strike images decode via ShareableBitmap::createReadOnly (maps non-CoW) and
createImage (hardcodes DontCopyBackingStore), so the CGImage is a zero-copy view
over pages the WebContent process still maps read-write. We handed those straight
to CTEmojiImageStrike and ran -[CTEmojiImageAsset imageData] over them, so the
sender could rewrite the pixels mid-encode. imageData was called twice as well,
once to null-check and once for the payload, which only widens the window. No user
interaction is needed: setupServicesMenu is reached purely by the sender setting
ContextMenuContextData::type() to ServicesMenu.

Snapshot each strike first. createFromImagePixels copies into a freshly allocated
SharedMemory that nobody else holds a handle to, so the encoder cannot see the
sender's writes. And call imageData once.

alignmentInset was unvalidated as well, so a non-finite FloatSize went straight
into CTEmojiImageStrike. Reject that at the IPC boundary and again at the point of
use. No caps on the strike count or the metadata strings: those operands cost the
sender as much as they cost us, and a guessed limit on the wire would terminate the
WebContent process the first time a legitimate asset outgrew it.

Also wrapped the CoreText calls in BEGIN_BLOCK_OBJC_EXCEPTIONS and fixed a nil
insert into the provenance dictionary, where the guard checked the identifier's
length but inserted the credit.

Test: Tools/TestWebKitAPI/Tests/WebCore/cocoa/MultiRepresentationHEICAttachment.mm

* Source/WebCore/editing/cocoa/AttributedString.mm:
(WebCore::createStrikeImageSnapshot):
(WebCore::toWebMultiRepresentationHEICAttachment):
* Source/WebCore/editing/cocoa/TextAttachmentForSerialization.h:
(WebCore::isValidMultiRepresentationHEICImageSize):
(WebCore::MultiRepresentationHEICAttachmentSingleImage::isValid const):
(WebCore::MultiRepresentationHEICAttachmentData::isValid const):
* Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in:
* Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* Tools/TestWebKitAPI/Tests/WebCore/cocoa/MultiRepresentationHEICAttachment.mm: Added.
(TestWebKitAPI::representativeAttachmentData):
(TestWebKitAPI::stringOfLength):
(TestWebKitAPI::TEST(MultiRepresentationHEICAttachment, AcceptsRepresentativeData)):
(TestWebKitAPI::TEST(MultiRepresentationHEICAttachment, AcceptsUnboundedMetadataStrings)):
(TestWebKitAPI::TEST(MultiRepresentationHEICAttachment, AcceptsFiniteImageSize)):
(TestWebKitAPI::TEST(MultiRepresentationHEICAttachment, RejectsNonFiniteImageSize)):
(TestWebKitAPI::TEST(MultiRepresentationHEICAttachment, RejectsNonFiniteImageSizeInAnyImage)):
(TestWebKitAPI::TEST(MultiRepresentationHEICAttachment, AcceptsUnboundedImageCount)):
(TestWebKitAPI::firstByteOf):
(TestWebKitAPI::TEST(MultiRepresentationHEICAttachment, StrikeSnapshotDoesNotAliasSenderMemory)):

Identifier: 316606.768@safari-7625-branch

Before / after

Loading diff…