From ffbe9ed4187aa95faeb1b65a9c1206f06014f9e8 Mon Sep 17 00:00:00 2001 From: ankuper Date: Thu, 2 Jul 2026 14:11:40 -0400 Subject: [PATCH] fix(display): guard DrawingContext against malloc-null image buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ASCGImageBuffer.initWithLength: calls malloc(length) with no null check. When length is oversized (e.g. from a bad drawingSize during chat photo layout), malloc can return NULL. CGContext(data: nil, ...) silently succeeds anyway — CoreGraphics falls back to its own internally-managed buffer, masking the failure. The later memset(self.bytes, 0, self.length) in DrawingContext.init then writes through the null imageBuffer pointer and segfaults (confirmed via crash report: ESR = Data Abort byte write Translation fault, FAR = 0x0, __bzero on the stack, ASCGImageBuffer visible in nearby registers — device crash while scrolling chats, build 33193). Fail the init gracefully (return nil) as soon as the buffer comes back null, matching the other guarded failure paths already in this initializer (non-positive size, CGContext creation failure). --- submodules/Display/Source/GenerateImage.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/submodules/Display/Source/GenerateImage.swift b/submodules/Display/Source/GenerateImage.swift index 9ce05cc1d4f..c4b95e574ac 100644 --- a/submodules/Display/Source/GenerateImage.swift +++ b/submodules/Display/Source/GenerateImage.swift @@ -638,6 +638,15 @@ public class DrawingContext { self.length = self.bytesPerRow * Int(scaledSize.height) self.imageBuffer = ASCGImageBuffer(length: UInt(self.length)) + if Int(bitPattern: self.imageBuffer.mutableBytes) == 0 { + // malloc(length) failed (e.g. an oversized allocation from a bad + // drawingSize). CGContext(data: nil, ...) below would silently + // succeed using CG's own internal buffer, masking the failure + // until the later memset(self.bytes, ...) writes through this + // null pointer and segfaults. Fail the init instead, matching + // the other guarded failure paths in this initializer. + return nil + } if opaque { self.bitmapInfo = DeviceGraphicsContextSettings.shared.opaqueBitmapInfo