以下代码用于将sockaddr
转换为sockaddr_in6
以获取IPv6地址:
extension sockaddr {
private var addressV6: String {
var me = self
var buffer = [Int8](repeating: 0, count: Int(INET6_ADDRSTRLEN))
withUnsafePointer(to: &me) {
$0.withMemoryRebound(to: sockaddr_in6.self, capacity: 1) {
var addrV6 = $0.pointee.sin6_addr
inet_ntop(AF_INET6, &addrV6, &buffer, socklen_t(INET6_ADDRSTRLEN))
}
}
return String(cString: buffer)
}
}
当我使用Address Sanitizer在Xcode 9 beta中运行代码时,执行在这一行停止:
var addrV6 = $0.pointee.sin6_addr
随着以下消息(以及大量的内存信息):
AddressSanitizer:地址0x000131810077处的堆栈缓冲区溢出
pc 0x00010a3c06d5 bp 0x7fff55ded010 sp 0x7fff55ded008读取大小16
在0x000131810077线程T0
我可以理解,ASAN担心我正在读取
sockaddr
的边界以获取完整的sockaddr_in6
(sockaddr
是16个字节,sockaddr_in6
是28个字节)。但是由于这个原因,我似乎无法使用ASAN测试应用程序的其余部分。任何使用
withMemoryRebound
都会使ASAN跳闸似乎有点不可思议。我试图以不同的方式编写它,甚至使用
Data
作为字节的容器。但是我似乎总是以触发ASAN的解决方案告终。我的代码有问题吗?
还是可以以某种方式忽略ASAN中的此功能?
最佳答案
getifaddrs
函数返回的指针看起来像sockaddr
指针,但实际上是指向sockaddr_in
或sockaddr_in6
的指针。通过将addressV6
函数移动到sockaddr
上的扩展名,内存被复制并剪切为sockaddr
结构的大小。如果是IPv6,宝贵的地址信息将会丢失。
新的(修剪过的)sockaddr
永远不会转换为触发SAN的sockaddr_in6
。
有关更多信息,请参见:
Swift getnameinfo unreliable results for IPv6
谢谢@MartinR为我提供帮助!