open static func PBKDF2(_ password: String, salt: Data,
prf: PRFAlg, rounds: UInt32) throws -> Data {
var result = Data(count:prf.cc.digestLength)
let passwData = password.data(using: String.Encoding.utf8)!
let status = result.withUnsafeMutableBytes {
(passwDataBytes: UnsafeMutablePointer<UInt8>) -> CCCryptorStatus in
return CCKeyDerivationPBKDF!(PBKDFAlgorithm.pbkdf2.rawValue,
(passwData as NSData).bytes, passwData.count,
(salt as NSData).bytes, salt.count,
prf.rawValue, rounds,
passwDataBytes, result.count)
}
guard status == noErr else { throw CCError(status) }
return result
}
result.withUnsafeMutableBytes在Xcode 10中给出错误,在Xcode 9中它是一个警告。
答案 0 :(得分:16)
这是SE-0176 Enforce Exclusive Access to Memory的结果,它是在Swift 4中实现的 并且在Swift 4.2中更严格。
解决方案是将计数分配给单独的变量:
let count = result.count
let status = result.withUnsafeMutableBytes {
(passwDataBytes: UnsafeMutablePointer<UInt8>) -> CCCryptorStatus in
return CCKeyDerivationPBKDF(..., count)
}
或捕获捕获列表中的计数:
let status = result.withUnsafeMutableBytes { [ count = result.count ]
(passwDataBytes: UnsafeMutablePointer<UInt8>) -> CCCryptorStatus in
return CCKeyDerivationPBKDF(..., count)
}
另请参阅Swift论坛中的Overlapping access warning in withUnsafeMutableBytes
withUnsafeMutableBytes(_ :)是Data上的一种变异方法,因此它需要在调用期间对数据进行写访问。通过访问闭包中的data.count,您将开始一个与当前写访问冲突的新数据读取。
您还可以在闭包的捕获列表中捕获数据副本或其计数:...
在独占访问开始之前,对闭包形成时的值进行评估,并按值捕获结果,避免重叠访问。
和this comment in 相应的拉取请求:
这里适当的解决方法是复制闭包外部的缓冲区计数,并将其传递给inet_ntop()。