Contents
  1. 1. Malloc Scribble
    1. 1.1. 野指针嗅探
  2. 2. 内存初始化
  3. 3. Xcode 上的 malloc scribble
  4. 4. libmalloc

Malloc Scribble

If set, fill memory that has been allocated with 0xaa bytes.  This increases the likelihood that a program
making assumptions about the contents of freshly allocated memory will fail.  Also if set, fill memory that
has been deallocated with 0x55 bytes.  This increases the likelihood that a program will fail due to
accessing memory that is no longer allocated. Note that due to the way in which freed memory is managed
internally, the 0x55 pattern may not appear in some parts of a deallocated memory block

这是 malloc 里的文档说明,在 Mac 终端打下面这个命令就有

man malloc

除了 malloc scribble 还有 MallocDebugReport、MallocStackLogging、MallocStackLoggingNoCompact 等等。

这个功能说是开启了之后 malloc 申请的内存块全填充 0xaa;free 之后全填充 0x55。malloc 之后如果没有做初始化就会跪,free 之后继续用也要跪。

野指针嗅探

有人利用 0x55 这个特点开发了野指针嗅探器,提升野指针崩溃的概率达到获取事故现场信息的目的。

https://blog.csdn.net/tencent_bugly/article/details/46277055

关键核心逻辑是使用 fishhook 替换系统 free 调用,填充 0x55. 但是填完了 0x55 又有可能被别的正常内容覆盖。

内存初始化

char *zone = (char *)malloc(sizeof(char) * 100)
memset(zone, 0, sizeof(zone) / sizeof(zone[0]));

这样初始化就是有问题的,参看 https://blog.csdn.net/KangRoger/article/details/20653255

sizeof(zone) 的值是 8,32 位🐔是 4,因为 zone 是指针。

https://blog.csdn.net/ljob2006/article/details/4872167 这篇文章对指针、数组名讲解的很好,其中有段红色的字醍醐灌顶。

sizeof 是操作符,不是函数。

这样就很好理解 sizeof 为啥知道数组、变量类型大小,却不知 malloc 内存块大小。因为前者都能在编译期确定,而后者确定不了。想让编译期确定一个 malloc 内存块的大小是不现实的。

Xcode 上的 malloc scribble

更新 需要同时开启 malloc guard 开关才会有强制 crash 提示。

Xcode 可以设置环境变量打开 malloc scribble 开关,这样就直接抓住了上文提到内存初始化错误的 bug。这样的 bug 在线上可能不会有问题,malloc 得到的内存块可能刚好是干净的(freshly)。但是在内存紧张的时候可能就分配到了不干净的块,就容易出问题。

zone 是字符串,如果调用 strlen 这样的方法由于末尾填 0 有误,直接跑到旁边的内存上了。非法操作内存,于是崩溃。

libmalloc

https://opensource.apple.com/source/libmalloc/libmalloc-53.1.1/src/malloc.c.auto.html

Contents
  1. 1. Malloc Scribble
    1. 1.1. 野指针嗅探
  2. 2. 内存初始化
  3. 3. Xcode 上的 malloc scribble
  4. 4. libmalloc