Turning Random Obj‑C Wild‑Pointer Crashes into Deterministic Bugs

This article explains why Obj‑C wild‑pointer crashes appear random, analyzes various memory‑state scenarios after object deallocation, and shows how to force deterministic crashes by filling freed memory with inaccessible patterns using Xcode's Enable Scribble and a custom free‑hook implementation.

Tencent TDS Service
Tencent TDS Service
Tencent TDS Service
Turning Random Obj‑C Wild‑Pointer Crashes into Deterministic Bugs

The author, a Tencent iOS audio‑video engineer, discusses how to increase the crash detection rate by exposing hidden random crashes, focusing on Obj‑C wild‑pointer issues.

Wild pointers occur when an Obj‑C object is released but the pointer is not cleared, leading to unpredictable crashes because the freed memory may still be accessed.

Two categories of crashes are identified:

Logic that never reaches the erroneous code (coverage issue).

Logic that reaches the code but the wild pointer does not always cause a crash, depending on the memory state.

Possible memory states after deallocation are enumerated:

The memory remains unchanged; the crash may or may not happen.

The memory is unchanged but the object's destructor removed essential data, causing possible crashes when accessing dependent objects.

The memory is overwritten with inaccessible data, leading to a guaranteed crash (commonly on objc_msgSend).

The memory is overwritten with accessible data, so crashes are random or rare.

The memory is overwritten with accessible data, but subsequent accesses corrupt other data, causing occasional crashes.

The memory is freed again, which is almost always a crash.

A diagram (image) illustrates these scenarios.

Example code that often does not crash:

UIView* testObj=[[UIView alloc] init];
[testObj release];
[testObj setNeedsLayout];

To make the crash deterministic, the author uses Xcode’s "Enable Scribble" feature, which fills freed memory with the pattern 0x55, causing immediate crashes on objc_msgSend.

Because this cannot be used by testers, a custom solution is built by hooking the C free function. The steps include:

Detect when memory is freed and immediately overwrite it.

Choose free as the hook target for broad coverage.

Implement the hook using the fishhook library.

Determine the size of the freed block via malloc_size.

Overwrite the block with 0x55, matching Xcode’s behavior.

Implementation of the hooked free:

void safe_free(void* p){
    size_t memSize = malloc_size(p);
    memset(p, 0x55, memSize);
    orig_free(p);
    return;
}

Testing shows that this method reliably triggers crashes similar to Enable Scribble, allowing developers to catch wild‑pointer bugs early.

Remaining challenges include cases where the overwritten pattern is later overwritten, why the pattern sometimes appears as 0x55555561, handling crashes caused by system code, and dealing with wild pointers that are not used as pointers.

The article concludes with a promise to explore further solutions in future installments.

iOSMemory DebuggingCrash Detectionfree hookObj-Cwild pointer
Tencent TDS Service
Written by

Tencent TDS Service

TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.