16 December 2025
Imagine if you could write C code and the computer would detect and abort immediately if you wrote one byte past the end of your heap allocation—or if you tried to access it after it was freed. It sounds like AddressSanitizer, right? It’s a useful tool but slow and often annoying to instrument builds. Now, imagine if this kind of protection was turned on all the time, running in production builds on your users’ devices, and there was no performance penalty for doing so.
No need to imagine: Apple has already shipped it. It’s called Memory Integrity Enforcement. If you have one of their latest processors, the A19 or M5, this capability is already in your …
16 December 2025
Imagine if you could write C code and the computer would detect and abort immediately if you wrote one byte past the end of your heap allocation—or if you tried to access it after it was freed. It sounds like AddressSanitizer, right? It’s a useful tool but slow and often annoying to instrument builds. Now, imagine if this kind of protection was turned on all the time, running in production builds on your users’ devices, and there was no performance penalty for doing so.
No need to imagine: Apple has already shipped it. It’s called Memory Integrity Enforcement. If you have one of their latest processors, the A19 or M5, this capability is already in your hands. Third party developers can opt in to have the same protection applied to their own apps. Below, I’m going to show how this looks in Xcode.
It’s difficult to overstate how cool this is. No, not all security bugs are memory bugs, and not all memory bugs are security bugs… but dang, Apple has raised the bar. You’re not going to get anything like this today on PC or Android. Modern ARM chips have MTE but it’s not widely used and it only goes so far on its own. From Apple’s post:
our analysis showed that while EMTE had great potential as specified, a rigorous implementation with deep hardware and operating system support could be a breakthrough that produces an extraordinary new security mechanism. … Ultimately, we determined that to deliver truly best-in-class memory safety, we would carry out a massive engineering effort spanning all of Apple — including updates to Apple silicon, our operating systems, and our software frameworks. This effort, together with our highly successful secure memory allocator work, would transform MTE from a helpful debugging tool into a groundbreaking new security feature.
Okay, big claims. Let’s write some bugs and see this in action then.
I created a new iOS project in Xcode and had to do three things to turn on the protection.
The first step is to add the Enhanced Security capability under Signing & Capabilities for the app target. This provides various goodies that are explained in Apple’s docs:
I decided I would add a Static Library target containing some buggy Objective-C code to see if MIE would pick it up. To make this build as part of my app I had to add arm64e to Architectures. It seems that having separate build artefacts is how you can support both MTE and non-MTE devices.
Less obviously, Hardware Memory Tagging is not actually enabled by default in the Run scheme. Edit the scheme, and in the Diagnostics tab toggle on Hardware Memory Tagging.
Finally, to be clear, you do actually have to run this on a modern physical device with support for MIE in the processor.
Let’s add some code. Here’s an ObjC method written in a C style. It creates a heap allocation, writes some data to it, then returns the pointer. It is assumed the caller will free the returned buffer later.
+ (char *)makeMeAString {
char *ret = malloc(128);
int i = 0;
while (i < 127) {
ret[i] = 'a';
i++;
}
ret[i] = 0;
return ret;
}
I will then call it from Swift.
if let s = OutOfBoundsLib.makeMeAString() {
let swiftString = String(cString: s)
print("String: \(swiftString)")
}
This works just fine so far.
Suppose we make a classic off-by-one error. Let’s change < 127 to < 128 so that the terminating null is accidentally written past the end of the allocation.
while (i < 128) {
ret[i] = 'a';
i++;
}
Would you look at that runtime error? Isn’t it beautiful? "Heap buffer overflow by 1 bytes"
Let’s change it back and try something else: let’s insert a free() just before we return the pointer to the value.
ret[i] = 0;
free(ret); // BAD IDEA
return ret;
"Use of deallocated memory". It’s not going to get much clearer than that. This time we’re seeing the error in Swift because that’s where the freed pointer is actually dereferenced.
This little demo only covers a small part of MIE but hopefully you get the idea. It’s game-changing to have so much visibility over memory bugs at the moment the corruption occurs.
MIE will be a wonderful complement to the adoption of memory-safe languages like Rust and Swift. We can use legacy libraries with more confidence and it will help catch certain mistakes if we do mess up when we reach for unsafe {} or UnsafeMutablePointer. Importantly, MIE doesn’t provide any way to recover when something bad happens. It just makes your app crash. That’s much better than an attacker achieving RCE but it’s also not great UX. Pervasive use of memory-safe languages is how we will avoid reaching those invalid states in the first place.
With all its resources, I assume that Apple internally performs extensive static analysis and fuzzing on its C-based libraries. The same cannot be said for the libraries used inside third-party apps. I expect that when MTE is enabled many of them will crash. A lot. Then they will have to get fixed. The best part is that some of those libraries will be open source ones which are also used on non-Apple platforms. The always-on sanitiser of new Apple hardware is going to help find and fix bugs which benefits other platforms too.
If you’re an Apple developer, don’t delay, check those boxes and see how your software holds up.
Serious Computer Business Blog by Thomas Karpiniec Posts RSS, Atom