CFURLCopyResourcePropertiesForKeys with kCFURLIsExcludedFromBackupKey (or CSBackupIsItemExcluded) on relative path overreleases

Originator:nriley
Number:rdar://15772932 Date Originated:08-Jan-2014 12:26 PM
Status:Open Resolved:
Product:OS X Product Version:10.9.1/13B42
Classification:Crash/Hang/Data Loss Reproducible:Always
 
Summary:
In CFURLCopyResourcePropertiesForKeys, if the key kCFURLIsExcludedFromBackupKey is provided and the CFURLRef encodes a relative path, the CFURLRef's embedded NSString is released, which may trigger a crash later in the program.

Steps to Reproduce:
Compile and run the attached source file as follows:

% clang -framework CoreFoundation -o sample sample.c
% ./sample sample.c


Expected Results:
The URL's string's retain count is the same before and after the call to CFURLCopyResourcePropertiesForKeys.

before - URL retain count: 1; string retain count: 1
[...]
after - URL retain count: 1; string retain count: 1


Actual Results:
The URL's string is released by CFURLCopyResourcePropertiesForKeys:

before - URL retain count: 1; string retain count: 1
[...]
after - URL retain count: 1; string retain count: 1152921504606846975


Version:
10.9.1/13B42

Notes:
Workaround: Explicitly retain the CFURLRef's string, e.g. CFRetain(CFURLGetString(url));

Configuration:
This problem exists on OS X 10.9.1 and OS X 10.8.5 in both 32 and 64-bit.

It does not occur if you pass an absolute path to CFStringCreateWithFileSystemRepresentation.

It does not occur if you supply other keys with CFURLCopyResourcePropertiesForKeys.  That is, any combination of keys which includes kCFURLIsExcludedFromBackupKey has triggered the problem.

[Attached file is uploaded to <http://sabi.net/temp/15772932.c>.]

Update:

If you pass a relative path to an item within a package, even the workaround described in my initial report does not work, and the application crashes.

The issue is actually in CSBackupIsItemExcluded.

See the attachment 'excluded.c'; compile with 'clang -framework CoreServices -o excluded excluded.c'.

% cd /Applications                                                               
% /path/to/excluded Safari.app         
<CFURL 0x7fdd4bc08120 [0x7fff71428110]>{string = Safari.app, encoding = 134217984
	base = <CFURL 0x7fdd4bc080b0 [0x7fff71428110]>{string = file://localhost/Applications/, encoding = 134217984, base = (null)}}
before - URL retain count: 2; string retain count: 2
after - URL retain count: 2; string retain count: 1

But even overretaining the URL and its string when passing a relative path to an item within a package, another CFURL's embedded CFString is overreleased:

% NSZombieEnabled=YES lldb -- /path/to/excluded Safari.app/Contents
Current executable set to '/path/to/excluded' (x86_64).
(lldb) run
Process 83022 launched: '/path/to/excluded' (x86_64)
<CFURL 0x10010a3b0 [0x7fff71428110]>{string = Safari.app/Contents, encoding = 134217984
	base = <CFURL 0x1001080d0 [0x7fff71428110]>{string = file://localhost/Applications/, encoding = 134217984, base = (null)}}
before - URL retain count: 2; string retain count: 2
2014-01-25 11:05:28.436 excluded[83022:f0b] *** -[CFString release]: message sent to deallocated instance 0x10030a870
Process 83022 stopped
* thread #1: tid = 0x1c03, 0x00007fff86381f2e CoreFoundation`___forwarding___ + 158, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x00007fff86381f2e CoreFoundation`___forwarding___ + 158
CoreFoundation`___forwarding___ + 158:
-> 0x7fff86381f2e:  callq  0x7fff8647c780            ; symbol stub for: getpid
   0x7fff86381f33:  movl   %eax, %edi
   0x7fff86381f35:  movl   $9, %esi
   0x7fff86381f3a:  callq  0x7fff8647c7d4            ; symbol stub for: kill
(lldb) bt
* thread #1: tid = 0x1c03, 0x00007fff86381f2e CoreFoundation`___forwarding___ + 158, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x00007fff86381f2e CoreFoundation`___forwarding___ + 158
    frame #1: 0x00007fff86381e18 CoreFoundation`_CF_forwarding_prep_0 + 232
    frame #2: 0x00007fff8630928a CoreFoundation`CFRelease + 170
    frame #3: 0x00007fff86311313 CoreFoundation`__CFURLDeallocate + 35
    frame #4: 0x00007fff863093df CoreFoundation`CFRelease + 511
    frame #5: 0x00007fff87bea9d3 CarbonCore`CSBackupIsItemExcluded + 887
    frame #6: 0x0000000100000e24 excluded`main + 212
    frame #7: 0x00007fff8a7b67e1 libdyld.dylib`start + 1

Again, if you use absolute paths, there are no problems in either scenario.

[Attached file is uploaded to <http://sabi.net/temp/15772932-excluded.c>.]

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!