我正在使用黑客攻击和保护iOS应用程序(相关部分“Here”)中概述的技术来擦除NSString
的基础缓冲区,如下所示
代码:
NSString *s = [NSString stringWithFormat:@"Hello"];
unsigned char *text = (unsigned char*)CFStringGetCStringPtr((CFStringRef)s, CFStringGetSystemEncoding());
if (text != NULL)
{
memset(text, 0, [s length]);
}
这是有效的,除非字符串是某个值。
// The following crashes with EXC_ACCESS_ERROR on memset
NSString *s = [NSString stringWithFormat:@"No"];
NSString *s = [NSString stringWithFormat:@"Yes"];
// These work fine though
NSString *s = [NSString stringWithFormat:@"Hello"];
NSString *s = [NSString stringWithFormat:@"Do"];
NSString *s = [@"N" stringByAppendingString:@"o"];
看起来某些字符串不是在堆上创建的,而是通过使其指向只读字符串表进行优化,即使该字符串是在堆上创建的。
有没有人对这种行为有更深入的了解?
答案 0 :(得分:1)
实际上,常量字符串不会在堆上创建并且位于只读内存中。这包括一些看起来像运行时但是编译时常量的例子,你的例子就是这样的陈述。
使用此语句片段,没有理由不使它成为编译时常量。
[NSString stringWithFormat:@"No"]
相当于:
@"No"
建议,提交请求安全字符串类的错误报告,我有。有几个已经提交,我被告知,如果有足够的(无论金额多少)是文件,它将实现它。
可以继承NSString
,但这并不容易,但是你将控制实际的缓冲区,并且由于Apple改变了实现细节,它不应该受到可能的失败。我成功地做到了。
答案 1 :(得分:1)
NSString *s = [NSString stringWithFormat:@"No"];
将优化为NSString *s = @"No";
,因为格式中没有替换。分配文字将为您提供指向已加载二进制文件的只读文本段的指针。
NSString *s = [@"N" stringByAppendingString:@"o"];
将在堆上创建一个新字符串并返回对它的引用。即使数据类型NSString
是只读的,堆也是可读写的。
当您获得指向底层数据的CString指针时,它指向第一种情况下的只读数据,或者指向第二种情况下的读写数据。 memset将在只读内存上失败,但在读写时会成功。