我正在尝试调查在我的代码中访问strlen函数中的地址0触发的恐慌消息,该代码基本上是C++,结合了Objective-C变量。

产生恐慌的方法不能直接从ARC引擎访问strlen,而是要尝试找出strlen用作自动释放变量的一部分。

根据从反汇编程序复制的下一个块,看来[rax UTF8String]的输出产生的是null而不是有效的字符串,这最终导致崩溃。也许有人可以告诉我,在对变量autoreleasing进行编码后,需要进行此检查的Objective-C的内部布局是什么。

*(int8_t *)(r15 + rbx) = 0x0;
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator=(r13 + 0x198, &var_60);
rax = [var_98 orgName];
rax = [rax retain];
rax = objc_retainAutorelease(rax);
var_70 = rax;
r14 = [rax UTF8String];
var_90 = intrinsic_movaps(var_90, 0x0);
var_80 = 0x0;
r15 = strlen(r14);
if (r15 >= 0xfffffffffffffff0) goto loc_10001267b;
if (r15 < 0x17) {
        r12 = &var_8F;
        *(int8_t *)(r12 - 0x1) = r15 + r15;
        if (r15 != 0x0) {
                memcpy(r12, r14, r15);
        }
}
else {
        r12 = operator new(r15 + 0x10 & 0xfffffffffffffff0);
        var_80 = r12;
        var_90 = r15 + 0x10 & 0xfffffffffffffff0 | 0x1;
        memcpy(r12, r14, r15);
}

最佳答案

ARC仅插入retain/release/autorelease指令。它不会插入UTF8Stringstrlen之类的内容。

objc_retainAutoreleaseretain + autorelease的组合。 autorelease操作不会释放该值,而是将一个对象放入当前的“自动释放池”中(就像标记该对象以供将来使用)。

在此代码中,我假定orgName将NSString返回到rax,然后通过使用NSString将此UTF8String转换为C字符串,并将其放置在r14中。由于某种原因,此代码的作者决定(奇怪的是)不使用orgName.length,而是使用strlen。因此,此字符串的长度orgName放入r15中。

如果orgName.length(在r15中)小于0x17,它将C字符串复制到var_8F
否则,它将分配一个新的缓冲区r12并在其中复制orgName C字符串。
*(int8_t *)(r12 - 0x1) = r15 + r15;行很奇怪。就像var_8F在var_8F之前有一个字节大小的字段,并在其中放置字符串长度的两倍(长度很小,所以可以容纳,但为什么要增加一倍?)。

关于c++ - Objective-C变量布局,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50783062/

10-09 16:13