Re: NSData, CFData maximum length question
Re: NSData, CFData maximum length question
- Subject: Re: NSData, CFData maximum length question
- From: Ben Gollmer <email@hidden>
- Date: Thu, 22 Mar 2012 02:44:50 -0400
On Mar 22, 2012, at 2:12 AM, Seth Willits wrote:
> On Mar 21, 2012, at 10:49 PM, Seth Willits wrote:
>
>> On Mar 21, 2012, at 6:00 PM, Grandinetti Philip wrote:
>>
>>> I am confused about different behavior I'm seeing with CFData and NSData. If I create a new project in XCode 4.3.1 as a Core Foundation command line tool, and enter the code below…
>>
>> You've triggered a bug!
>>
>> And it took me a long time, but I found it. The bug is in __CFDataRoundUpCapacity, and has to do with a bad (1 << ….) which should be (1L << …).
>>
>> I'll file a report.
>
> Filed as 11097403. And yeah, setting the length to anything > 0 when the data is created will avoid the bug because the CFData is not "growable", and CFDataSetLength is handled a little different for growable CFDatas vs fixed-length mutable ones.
>
> I'm not sure what [NSMutableData dataWithCapacity:0] does, but it's not a simple call to CFDataCreateMutable(kCFAllocatorDefault, 0) which is why it behaves differently as well.
Calling CFDataSetLength() (or CFDataIncreaseLength(), which simply calls through to CFDataSetLength()) on a non-growable CFMutableData() short-circuits the problematic __CFDataGrow() -> __CFDataRoundUpCapacity() call chain, but there's an interesting side effect. Because CFAssert is #defined out on non-debug builds of CoreFoundation, the function exits the if loop, but still calls __CFDataSetLength() and __CFDataSetNumBytesUsed(). This can result in the length being larger than the capacity:
<CFData 0x101f13e60 [0x7fff7b99efc0]>{length = 32, capacity = 16, bytes = 0x00 ... 00}
That means that this code:
CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 16);
CFDataSetLength(data, 1ULL << 30);
CFShow(data);
will not crash or complain on the CFDataSetLength() call, but it will segfault on the CFShow(), as __CFDataCopyDescription() goes tramping off the end of the buffer.
Checking CFDataGetLength() after a bad CFDataSetLength() would lead you to believe you had all the requested space available. Unfortunately, there doesn't seem to be any way to inspect the capacity of an existing CFMutableData object.
--
Ben
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden