CFRelease 在 iOS10 中崩溃
CFRelease crash in iOS10
下面是我的代码,在 iOS 9.
之前都可以正常工作
- (NSData *)encryptWithDataPublicKey:(NSString*)data keyTag:(NSString*)tag
{
SecKeyRef publicKey = NULL;
NSData *publicTag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
NSMutableDictionary *queryPublicKey =
[[NSMutableDictionary alloc] init];
[queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
[queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
OSStatus status = SecItemCopyMatching
((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKey);
NSData *encodedData = nil;
if (status == noErr && publicKey) {
NSData *dataToEncrypt = [data dataUsingEncoding:NSUTF8StringEncoding];
encodedData = [self encryptData:dataToEncrypt withKeyRef:publicKey];
CFRelease(publicKey);
}
return encodedData;
}
此方法在 iOS 9.x 之前一直有效,但今天我将 XCode 更新为 8 并在 iOS 10 上更新了 运行设备。应用程序崩溃于
CFRelease(公钥).
下面是崩溃前控制台的日志。
could not load any Objective-C class information. This will
significantly reduce the quality of type information available
无法准确找到问题。
当我启用 Zombie 并重现崩溃时。以下是来自控制台的日志。
*** -[非类型发布]: 消息发送到释放实例 0x170225880
提前致谢。
我遇到了问题。
有一个内部方法 encodedData = [self encryptData:dataToEncrypt withKeyRef:publicKey];
SecKeyRef 对象的释放位置。
但我想知道这在 iOS9 之前是如何工作的???????
-(NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
const uint8_t *srcbuf = (const uint8_t *)[data bytes];
size_t srclen = (size_t)data.length;
size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
void *outbuf = malloc(block_size);
size_t src_block_size = block_size - 11;
NSMutableData *ret = [[NSMutableData alloc] init];
for(int idx=0; idx<srclen; idx+=src_block_size){
size_t data_len = srclen - idx;
if(data_len > src_block_size){
data_len = src_block_size;
}
size_t outlen = block_size;
OSStatus status = noErr;
status = SecKeyEncrypt(keyRef,
kSecPaddingPKCS1,
srcbuf + idx,
data_len,
outbuf,
&outlen
);
if (status != 0) {
ret = nil;
break;
}else{
[ret appendBytes:outbuf length:outlen];
}
}
free(outbuf);
CFRelease(keyRef);
return ret;
}
在 encryptData:withKeyRef:
中,您在方法末尾有一个不平衡的 CFRelease
。该方法中没有任何内容保留 keyRef
,但您释放了它。删除该调用。
为什么之前没有崩溃?因为以前可能有其他东西在内部保留它,可能是缓存,也可能是其他东西。 Cocoa 不承诺过度发布会立即(或永远)导致崩溃。您遇到了未定义的行为。
不过,静态分析器没有检测到这一点,这让人非常苦恼。我会打开一个关于那个的错误报告 (bugreport.apple.com)。您有一个非常明显的内存管理违规,分析器应该已经发现了。
下面是我的代码,在 iOS 9.
之前都可以正常工作- (NSData *)encryptWithDataPublicKey:(NSString*)data keyTag:(NSString*)tag
{
SecKeyRef publicKey = NULL;
NSData *publicTag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
NSMutableDictionary *queryPublicKey =
[[NSMutableDictionary alloc] init];
[queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
[queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
OSStatus status = SecItemCopyMatching
((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKey);
NSData *encodedData = nil;
if (status == noErr && publicKey) {
NSData *dataToEncrypt = [data dataUsingEncoding:NSUTF8StringEncoding];
encodedData = [self encryptData:dataToEncrypt withKeyRef:publicKey];
CFRelease(publicKey);
}
return encodedData;
}
此方法在 iOS 9.x 之前一直有效,但今天我将 XCode 更新为 8 并在 iOS 10 上更新了 运行设备。应用程序崩溃于
CFRelease(公钥).
下面是崩溃前控制台的日志。
could not load any Objective-C class information. This will significantly reduce the quality of type information available
无法准确找到问题。
当我启用 Zombie 并重现崩溃时。以下是来自控制台的日志。
*** -[非类型发布]: 消息发送到释放实例 0x170225880
提前致谢。
我遇到了问题。 有一个内部方法 encodedData = [self encryptData:dataToEncrypt withKeyRef:publicKey];
SecKeyRef 对象的释放位置。
但我想知道这在 iOS9 之前是如何工作的???????
-(NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
const uint8_t *srcbuf = (const uint8_t *)[data bytes];
size_t srclen = (size_t)data.length;
size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
void *outbuf = malloc(block_size);
size_t src_block_size = block_size - 11;
NSMutableData *ret = [[NSMutableData alloc] init];
for(int idx=0; idx<srclen; idx+=src_block_size){
size_t data_len = srclen - idx;
if(data_len > src_block_size){
data_len = src_block_size;
}
size_t outlen = block_size;
OSStatus status = noErr;
status = SecKeyEncrypt(keyRef,
kSecPaddingPKCS1,
srcbuf + idx,
data_len,
outbuf,
&outlen
);
if (status != 0) {
ret = nil;
break;
}else{
[ret appendBytes:outbuf length:outlen];
}
}
free(outbuf);
CFRelease(keyRef);
return ret;
}
在 encryptData:withKeyRef:
中,您在方法末尾有一个不平衡的 CFRelease
。该方法中没有任何内容保留 keyRef
,但您释放了它。删除该调用。
为什么之前没有崩溃?因为以前可能有其他东西在内部保留它,可能是缓存,也可能是其他东西。 Cocoa 不承诺过度发布会立即(或永远)导致崩溃。您遇到了未定义的行为。
不过,静态分析器没有检测到这一点,这让人非常苦恼。我会打开一个关于那个的错误报告 (bugreport.apple.com)。您有一个非常明显的内存管理违规,分析器应该已经发现了。