Invalid pointers being passed to free() upon CFAllocatorSetDefault()
Invalid pointers being passed to free() upon CFAllocatorSetDefault()
- Subject: Invalid pointers being passed to free() upon CFAllocatorSetDefault()
- From: Alexander Potapenko <email@hidden>
- Date: Thu, 21 Jun 2012 01:17:15 +0400
Hi everyone,
(my apologies to those who've seen this email in the Google-only mailing list)
The following program:
====================================
$ cat t.mm
#import <Foundation/Foundation.h>
int main() {
#ifdef REPLACE
CFAllocatorSetDefault(kCFAllocatorMallocZone);
#endif
NSURL *base = [[NSURL alloc]
initWithString:@"file://localhost/Users/glider/Library/"];
NSURL *u = [[NSURL alloc] initWithString:@"Saved Application State"
relativeToURL:base];
return 0;
}
====================================
behaves incorrectly if CFAllocatorSetDefault is called:
$ clang++ t.mm -o t -DREPLACE -framework Foundation -g && ./t
t(47457) malloc: *** error for object 0x10ba14348: pointer being freed
was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
This happens because _CFRuntimeCreateInstance (which is called from
CFURLAlloc) checks whether the supplied allocator is
kCFAllocatorSystemDefault and, if it is not, stores the allocator
reference at the beginning of the allocated memory and returns the
pointer to the allocated memory plus sizeof(CFAllocatorRef). See
http://www.opensource.apple.com/source/CF/CF-550/CFRuntime.c for the
reference.
When the object is destroyed, nobody actually checks whether the
pointer was skewed and corrects it:
Breakpoint 1, 0x00007fff8f4e86c0 in malloc_error_break ()
(gdb) bt
#0 0x00007fff8f4e86c0 in malloc_error_break ()
#1 0x00007fff8f4e8805 in free ()
#2 0x00007fff9375ed53 in object_dispose ()
#3 0x00007fff8e295086 in -[NSObject dealloc] ()
#4 0x00007fff8e854d4f in -[NSURL(NSURL) initWithString:relativeToURL:] ()
#5 0x0000000100000ded in main () at t.mm:36
To the best of my knowledge, _CFRelease (see CFRuntime.c again) is the
only function that checks for the presence of the allocator reference
at the beginning of the memory block, but it isn't called while
destroying the object.
My two questions are:
1. Is this correct that kCFAllocatorSystemDefault, not
kCFAllocatorDefault (i.e. NULL), is treated specially? IIUC most of
the time the libraries just pass NULL as the allocator.
2. How do I work around this? Looking for a CFAllocator pointer before
each freed block within free() sounds lame (albeit efficient).
Interposing _CFRuntimeCreateInstance with my own implementation that
doesn't do dirty pointer tricks may be more correct, but it's too easy
to break down next time CFRuntime.c changes.
TIA,
Alexander Potapenko
Software Engineer
Google Moscow
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden