EXC_BAD_ACCESS (code=1) on an apparently valid address

I'm currently dealing with a really weird bug in my iOS app. It doesn't happen in the simulator, and it doesn't happen when I recompile the core of the app for x86 and run it on Mac or Linux.


It takes the form of an EXC_BAD_ACCESS when you do some particular thing. The code is 1, which apparently means KERN_INVALID_ADDRESS. In other words, the kernel says nothing is mapped at that address. But when I use the

memory region
command in lldb, it says there's a page mapped at that address with read and write permissions turned on. I've confirmed with debug logging that the region is mapped with mmap earlier in the program and never unmapped. (I haven't tried calling mach_vm_region_info, but I suspect it would return the same thing.)


So the question is, why would the kernel throw EXC_BAD_ACCESS with code 1 for an address that's apparently valid?


One clue: If you run the app in lldb over USB, runn

memory region ptr
, and then run
memory region
with no arguments, LLDB will crash, and the app just continues and works fine. Maybe
memory region ptr
caused some sort of probe that made the kernel realize the pointer was actually valid?

Replies

Please run your program outside of the debugger, have it crash, and then post a full crash report here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

The crash dump says the pointer is pointing to a gap in the VM space of size 0x4000.


Here's a bit more data:


Process 626 stopped
* thread #12, stop reason = EXC_BAD_ACCESS (code=1, address=0x106941224)
    frame #0: 0x00000001006e72a0 iSH`cpu_run [inlined] __mem_read(mem=<unavailable>, addr=<unavailable>, size=4) at memory.h:105 [opt]
   102    void *ptr = __mem_read_ptr(mem, addr);
   103    if (ptr == NULL)
   104        return false;
-> 105    memcpy(out, ptr, size);
   106    return true;
   107 }
   108 #define mem_read(mem, addr, value) __mem_read(mem, addr, (value), sizeof(*(value)))
Target 0: (iSH) stopped.
(lldb) c
Process 626 resuming
Process 626 stopped
* thread #12, stop reason = EXC_BAD_ACCESS (code=1, address=0x106941224)
    frame #0: 0x00000001006e72a0 iSH`cpu_run [inlined] __mem_read(mem=<unavailable>, addr=<unavailable>, size=4) at memory.h:105 [opt]
   102    void *ptr = __mem_read_ptr(mem, addr);
   103    if (ptr == NULL)
   104        return false;
-> 105    memcpy(out, ptr, size);
   106    return true;
   107 }
   108 #define mem_read(mem, addr, value) __mem_read(mem, addr, (value), sizeof(*(value)))
Target 0: (iSH) stopped.
(lldb) p ptr
(void *) $0 = 0x0000000106941224
(lldb) c
Process 626 resuming


I run the program in the debugger, it stops on a segfault, I press continue, and it stops in the same place. Then I print the address of the pointer, continue again, and it continues as if nothing had ever happened. This smells like a kernel bug to me.

I’m still interesting in seeing a crash report. It has a bunch of interesting info in and of itself, and it eliminates LLDB from the equation.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

After a lot of debugging this turned out to just be a boring use-after-munmap bug. The way it would work fine if you continued in LLDB was really weird, though. I still think that's a kernel bug, and that it's rare enough that I can morally justify not trying to make a minimal repro case and submitting a radar.