From d9afa74568eb11e872c660cef2f1b66c52f356d9 Mon Sep 17 00:00:00 2001 From: Andre Dieb Date: Wed, 21 Feb 2024 03:06:04 -0300 Subject: [PATCH] Avoid memory leak from hostent (#30) hostent is internally allocated by ares_parse_a_reply when we pass non-null pointer, and it expects the caller to freehostent(hostent). --- .../c-ares/DNSResolver_c-ares.swift | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Sources/AsyncDNSResolver/c-ares/DNSResolver_c-ares.swift b/Sources/AsyncDNSResolver/c-ares/DNSResolver_c-ares.swift index b7dc7fa..7953969 100644 --- a/Sources/AsyncDNSResolver/c-ares/DNSResolver_c-ares.swift +++ b/Sources/AsyncDNSResolver/c-ares/DNSResolver_c-ares.swift @@ -303,12 +303,6 @@ extension Ares { static let instance = AQueryReplyParser() func parse(buffer: UnsafeMutablePointer?, length: CInt) throws -> [ARecord] { - // `hostent` is not needed, but if we don't allocate and pass it as an arg c-ares will allocate one - // and free it automatically, and that might cause TSAN errors in `ares_free_hostent`. If we allocate - // it then we control when it's freed. - let hostentPtrPtr = UnsafeMutablePointer?>.allocate(capacity: 1) - defer { hostentPtrPtr.deallocate() } - let addrttlsPointer = UnsafeMutablePointer.allocate(capacity: Ares.maxAddresses) defer { addrttlsPointer.deallocate() } let naddrttlsPointer = UnsafeMutablePointer.allocate(capacity: 1) @@ -317,7 +311,7 @@ extension Ares { // Set a limit or else addrttl array won't be populated naddrttlsPointer.pointee = CInt(Ares.maxAddresses) - let parseStatus = ares_parse_a_reply(buffer, length, hostentPtrPtr, addrttlsPointer, naddrttlsPointer) + let parseStatus = ares_parse_a_reply(buffer, length, nil, addrttlsPointer, naddrttlsPointer) guard parseStatus == ARES_SUCCESS else { throw AsyncDNSResolver.Error(code: parseStatus, "failed to parse A query reply") } @@ -332,12 +326,6 @@ extension Ares { static let instance = AAAAQueryReplyParser() func parse(buffer: UnsafeMutablePointer?, length: CInt) throws -> [AAAARecord] { - // `hostent` is not needed, but if we don't allocate and pass it as an arg c-ares will allocate one - // and free it automatically, and that might cause TSAN errors in `ares_free_hostent`. If we allocate - // it then we control when it's freed. - let hostentPtrPtr = UnsafeMutablePointer?>.allocate(capacity: 1) - defer { hostentPtrPtr.deallocate() } - let addrttlsPointer = UnsafeMutablePointer.allocate(capacity: Ares.maxAddresses) defer { addrttlsPointer.deallocate() } let naddrttlsPointer = UnsafeMutablePointer.allocate(capacity: 1) @@ -346,7 +334,7 @@ extension Ares { // Set a limit or else addrttl array won't be populated naddrttlsPointer.pointee = CInt(Ares.maxAddresses) - let parseStatus = ares_parse_aaaa_reply(buffer, length, hostentPtrPtr, addrttlsPointer, naddrttlsPointer) + let parseStatus = ares_parse_aaaa_reply(buffer, length, nil, addrttlsPointer, naddrttlsPointer) guard parseStatus == ARES_SUCCESS else { throw AsyncDNSResolver.Error(code: parseStatus, "failed to parse AAAA query reply") }