From ee9c2b1f109344dc927a4bad397ca8f82801f239 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Tue, 29 Oct 2024 16:37:26 -0700 Subject: [PATCH] Fix a memory leak in `DispatchData.withUnsafeBytes` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `DispatchData.withUnsafeBytes` created a new `dispatch_data_t` by calling `dispatch_data_create_map`. I assume that the intention was that this memory was freed when `data` is destroyed, based on the presence of `_fixLifetime(data)` but `data` was just a plain `dispatch_data_t` C struct, that doesn’t have any cleanup operations associated with it when destroyed. To fix the leak, wrap the `dispatch_data_t` in a `DispatchData`, which takes over the ownership of the `dispatch_data_t` and releases it when `data` gets destroyed. Alternatively, `_fixLifetime` could have been replaced by `_swift_dispatch_release(unsafeBitCast(data, to: dispatch_object_t.self))` but I think using `DispatchData` is the cleaner solution. --- src/swift/Data.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/swift/Data.swift b/src/swift/Data.swift index 158ec1fe6..ac962d71c 100644 --- a/src/swift/Data.swift +++ b/src/swift/Data.swift @@ -110,7 +110,7 @@ public struct DispatchData : RandomAccessCollection { { var ptr: UnsafeRawPointer? = nil var size = 0 - let data = CDispatch.dispatch_data_create_map(__wrapped.__wrapped, &ptr, &size) + let data = DispatchData(data: CDispatch.dispatch_data_create_map(__wrapped.__wrapped, &ptr, &size)) let contentPtr = ptr!.bindMemory( to: ContentType.self, capacity: size / MemoryLayout.stride) defer { _fixLifetime(data) }