in Frameworks/CoreFoundation/Parsing.subproj/CFBinaryPList.c [1089:1589]
CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFSetRef keyPaths, CFPropertyListRef *plist) {
if (objects) {
*plist = CFDictionaryGetValue(objects, (const void *)(uintptr_t)startOffset);
if (*plist) {
// have to assume that '*plist' was previously created with same allocator that is now being passed in
CFRetain(*plist);
return true;
}
}
// at any one invocation of this function, set should contain the offsets in the "path" down to this object
if (set && CFSetContainsValue(set, (const void *)(uintptr_t)startOffset)) FAIL_FALSE;
// databytes is trusted to be at least datalen bytes long
// *trailer contents are trusted, even for overflows -- was checked when the trailer was parsed
uint64_t objectsRangeStart = 8, objectsRangeEnd = trailer->_offsetTableOffset - 1;
if (startOffset < objectsRangeStart || objectsRangeEnd < startOffset) FAIL_FALSE;
uint64_t off;
CFPropertyListRef *list;
uint8_t marker = *(databytes + startOffset);
switch (marker & 0xf0) {
case kCFBinaryPlistMarkerNull:
switch (marker) {
case kCFBinaryPlistMarkerNull:
*plist = kCFNull;
return true;
case kCFBinaryPlistMarkerFalse:
*plist = !(0) ? CFRetain(kCFBooleanFalse) : kCFBooleanFalse;
return true;
case kCFBinaryPlistMarkerTrue:
*plist = !(0) ? CFRetain(kCFBooleanTrue) : kCFBooleanTrue;
return true;
}
FAIL_FALSE;
case kCFBinaryPlistMarkerInt:
{
const uint8_t *ptr = (databytes + startOffset);
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
uint64_t cnt = 1 << (marker & 0x0f);
const uint8_t *extent = check_ptr_add(ptr, cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
if (16 < cnt) FAIL_FALSE;
// in format version '00', 1, 2, and 4-byte integers have to be interpreted as unsigned,
// whereas 8-byte integers are signed (and 16-byte when available)
// negative 1, 2, 4-byte integers are always emitted as 8 bytes in format '00'
// integers are not required to be in the most compact possible representation, but only the last 64 bits are significant currently
uint64_t bigint = _getSizedInt(ptr, cnt);
if (8 < cnt) {
CFSInt128Struct val;
val.high = 0;
val.low = bigint;
*plist = CFNumberCreate(allocator, static_cast<CFNumberType>(kCFNumberSInt128Type), &val);
} else {
*plist = CFNumberCreate(allocator, static_cast<CFNumberType>(kCFNumberSInt64Type), &bigint);
}
// these are always immutable
if (objects && *plist) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
case kCFBinaryPlistMarkerReal:
switch (marker & 0x0f) {
case 2: {
const uint8_t *ptr = (databytes + startOffset);
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
const uint8_t *extent = check_ptr_add(ptr, 4, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
CFSwappedFloat32 swapped32;
memmove(&swapped32, ptr, 4);
float f = CFConvertFloat32SwappedToHost(swapped32);
*plist = CFNumberCreate(allocator, kCFNumberFloat32Type, &f);
// these are always immutable
if (objects && *plist) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
case 3: {
const uint8_t *ptr = (databytes + startOffset);
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
const uint8_t *extent = check_ptr_add(ptr, 8, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
CFSwappedFloat64 swapped64;
memmove(&swapped64, ptr, 8);
double d = CFConvertFloat64SwappedToHost(swapped64);
*plist = CFNumberCreate(allocator, kCFNumberFloat64Type, &d);
// these are always immutable
if (objects && *plist) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
}
FAIL_FALSE;
case kCFBinaryPlistMarkerDate & 0xf0:
switch (marker) {
case kCFBinaryPlistMarkerDate: {
const uint8_t *ptr = (databytes + startOffset);
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
const uint8_t *extent = check_ptr_add(ptr, 8, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
CFSwappedFloat64 swapped64;
memmove(&swapped64, ptr, 8);
double d = CFConvertFloat64SwappedToHost(swapped64);
*plist = CFDateCreate(allocator, d);
// these are always immutable
if (objects && *plist) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
}
FAIL_FALSE;
case kCFBinaryPlistMarkerData: {
const uint8_t *ptr = databytes + startOffset;
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
CFIndex cnt = marker & 0x0f;
if (0xf == cnt) {
uint64_t bigint = 0;
if (!_readInt(ptr, databytes + objectsRangeEnd, &bigint, &ptr)) FAIL_FALSE;
if (LONG_MAX < bigint) FAIL_FALSE;
cnt = (CFIndex)bigint;
}
const uint8_t *extent = check_ptr_add(ptr, cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
*plist = CFDataCreateMutable(allocator, 0);
if (*plist) CFDataAppendBytes((CFMutableDataRef)*plist, ptr, cnt);
} else {
*plist = CFDataCreate(allocator, ptr, cnt);
}
if (objects && *plist && (mutabilityOption != kCFPropertyListMutableContainersAndLeaves)) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
case kCFBinaryPlistMarkerASCIIString: {
const uint8_t *ptr = databytes + startOffset;
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
CFIndex cnt = marker & 0x0f;
if (0xf == cnt) {
uint64_t bigint = 0;
if (!_readInt(ptr, databytes + objectsRangeEnd, &bigint, &ptr)) FAIL_FALSE;
if (LONG_MAX < bigint) FAIL_FALSE;
cnt = (CFIndex)bigint;
}
const uint8_t *extent = check_ptr_add(ptr, cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
CFStringRef str = CFStringCreateWithBytes(allocator, ptr, cnt, kCFStringEncodingASCII, false);
*plist = str ? CFStringCreateMutableCopy(allocator, 0, str) : NULL;
if (str) CFRelease(str);
} else {
*plist = CFStringCreateWithBytes(allocator, ptr, cnt, kCFStringEncodingASCII, false);
}
if (objects && *plist && (mutabilityOption != kCFPropertyListMutableContainersAndLeaves)) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
case kCFBinaryPlistMarkerUnicode16String: {
const uint8_t *ptr = databytes + startOffset;
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
CFIndex cnt = marker & 0x0f;
if (0xf == cnt) {
uint64_t bigint = 0;
if (!_readInt(ptr, databytes + objectsRangeEnd, &bigint, &ptr)) FAIL_FALSE;
if (LONG_MAX < bigint) FAIL_FALSE;
cnt = (CFIndex)bigint;
}
const uint8_t *extent = check_ptr_add(ptr, cnt, &err) - 1;
extent = check_ptr_add(extent, cnt, &err); // 2 bytes per character
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
size_t byte_cnt = check_size_t_mul(cnt, sizeof(UniChar), &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
UniChar *chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, 0);
if (!chars) FAIL_FALSE;
memmove(chars, ptr, byte_cnt);
for (CFIndex idx = 0; idx < cnt; idx++) {
chars[idx] = CFSwapInt16BigToHost(chars[idx]);
}
if (mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
CFStringRef str = CFStringCreateWithCharacters(allocator, chars, cnt);
*plist = str ? CFStringCreateMutableCopy(allocator, 0, str) : NULL;
if (str) CFRelease(str);
} else {
*plist = CFStringCreateWithCharacters(allocator, chars, cnt);
}
CFAllocatorDeallocate(kCFAllocatorSystemDefault, chars);
if (objects && *plist && (mutabilityOption != kCFPropertyListMutableContainersAndLeaves)) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
case kCFBinaryPlistMarkerUID: {
const uint8_t *ptr = databytes + startOffset;
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
CFIndex cnt = (marker & 0x0f) + 1;
const uint8_t *extent = check_ptr_add(ptr, cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
// uids are not required to be in the most compact possible representation, but only the last 64 bits are significant currently
uint64_t bigint = _getSizedInt(ptr, cnt);
if (UINT32_MAX < bigint) FAIL_FALSE;
*plist = _CFKeyedArchiverUIDCreate(allocator, (uint32_t)bigint);
// these are always immutable
if (objects && *plist) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
return (*plist) ? true : false;
}
case kCFBinaryPlistMarkerArray:
case kCFBinaryPlistMarkerSet: {
const uint8_t *ptr = databytes + startOffset;
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
CFIndex arrayCount = marker & 0x0f;
if (0xf == arrayCount) {
uint64_t bigint = 0;
if (!_readInt(ptr, databytes + objectsRangeEnd, &bigint, &ptr)) FAIL_FALSE;
if (LONG_MAX < bigint) FAIL_FALSE;
arrayCount = (CFIndex)bigint;
}
size_t byte_cnt = check_size_t_mul(arrayCount, trailer->_objectRefSize, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
const uint8_t *extent = check_ptr_add(ptr, byte_cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
byte_cnt = check_size_t_mul(arrayCount, sizeof(CFPropertyListRef), &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
STACK_BUFFER_DECL(CFPropertyListRef, buffer, arrayCount <= 256 ? arrayCount : 1);
list = (arrayCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory);
if (!list) FAIL_FALSE;
Boolean madeSet = false;
if (!set && 15 < curDepth) {
set = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
madeSet = set ? true : false;
}
if (set) CFSetAddValue(set, (const void *)(uintptr_t)startOffset);
if ((marker & 0xf0) == kCFBinaryPlistMarkerArray && keyPaths) {
// Only get a subset of this array
CFSetRef theseKeys, nextKeys;
__CFPropertyListCreateSplitKeypaths(kCFAllocatorSystemDefault, keyPaths, &theseKeys, &nextKeys);
Boolean success = true;
CFMutableArrayRef array = CFArrayCreateMutable(allocator, CFSetGetCount(theseKeys), &kCFTypeArrayCallBacks);
if (theseKeys) {
CFTypeRef *keys = (CFTypeRef *)malloc(CFSetGetCount(theseKeys) * sizeof(CFTypeRef));
CFSetGetValues(theseKeys, keys);
for (CFIndex i = 0; i < CFSetGetCount(theseKeys); i++) {
CFStringRef key = (CFStringRef)keys[i];
SInt32 intValue = CFStringGetIntValue(key);
if ((intValue == 0 && CFStringCompare(CFSTR("0"), key, 0) != kCFCompareEqualTo) || intValue == INT_MAX || intValue == INT_MIN || intValue < 0) {
// skip, doesn't appear to be a proper integer
} else {
uint64_t valueOffset;
Boolean found = __CFBinaryPlistGetOffsetForValueFromArray2(databytes, datalen, startOffset, trailer, (CFIndex)intValue, &valueOffset, objects);
if (found) {
CFPropertyListRef result;
success = __CFBinaryPlistCreateObjectFiltered(databytes, datalen, valueOffset, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, nextKeys, &result);
if (success) {
CFArrayAppendValue(array, result);
CFRelease(result);
} else {
break;
}
}
}
}
free(keys);
CFRelease(theseKeys);
}
if (nextKeys) CFRelease(nextKeys);
if (success) {
if (!(mutabilityOption == kCFPropertyListMutableContainers || mutabilityOption == kCFPropertyListMutableContainersAndLeaves)) {
// make immutable
*plist = CFArrayCreateCopy(allocator, array);
CFRelease(array);
} else {
*plist = array;
}
} else if (array) {
CFRelease(array);
}
} else {
for (CFIndex idx = 0; idx < arrayCount; idx++) {
CFPropertyListRef pl;
off = _getOffsetOfRefAt(databytes, ptr, trailer);
if (!__CFBinaryPlistCreateObjectFiltered(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, NULL, &pl)) {
while (idx--) {
CFRelease(list[idx]);
}
if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
if (madeSet) { CFRelease(set); }
FAIL_FALSE;
}
__CFAssignWithWriteBarrier((void **)list + idx, (void *)pl);
ptr += trailer->_objectRefSize;
}
if ((marker & 0xf0) == kCFBinaryPlistMarkerArray) {
if (mutabilityOption != kCFPropertyListImmutable) {
*plist = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
CFArrayReplaceValues((CFMutableArrayRef)*plist, CFRangeMake(0, 0), list, arrayCount);
for (CFIndex idx = 0; idx < arrayCount; idx++) {
CFRelease(list[idx]);
}
} else {
if (!kCFUseCollectableAllocator) {
*plist = __CFArrayCreateTransfer(allocator, list, arrayCount);
} else {
*plist = CFArrayCreate(allocator, list, arrayCount, &kCFTypeArrayCallBacks);
for (CFIndex idx = 0; idx < arrayCount; idx++) {
CFRelease(list[idx]);
}
}
}
} else {
if (mutabilityOption != kCFPropertyListImmutable) {
*plist = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
for (CFIndex idx = 0; idx < arrayCount; idx++) {
CFSetAddValue((CFMutableSetRef)*plist, list[idx]);
}
for (CFIndex idx = 0; idx < arrayCount; idx++) {
CFRelease(list[idx]);
}
} else {
if (!kCFUseCollectableAllocator) {
*plist = __CFSetCreateTransfer(allocator, list, arrayCount);
} else {
*plist = CFSetCreate(allocator, list, arrayCount, &kCFTypeSetCallBacks);
for (CFIndex idx = 0; idx < arrayCount; idx++) {
CFRelease(list[idx]);
}
}
}
}
}
if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
if (madeSet) {
CFRelease(set);
set = NULL;
}
if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
return (*plist) ? true : false;
}
case kCFBinaryPlistMarkerDict: {
const uint8_t *ptr = databytes + startOffset;
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
CFIndex dictionaryCount = marker & 0x0f;
if (0xf == dictionaryCount) {
uint64_t bigint = 0;
if (!_readInt(ptr, databytes + objectsRangeEnd, &bigint, &ptr)) FAIL_FALSE;
if (LONG_MAX < bigint) FAIL_FALSE;
dictionaryCount = (CFIndex)bigint;
}
dictionaryCount = check_size_t_mul(dictionaryCount, 2, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
size_t byte_cnt = check_size_t_mul(dictionaryCount, trailer->_objectRefSize, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
const uint8_t *extent = check_ptr_add(ptr, byte_cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
byte_cnt = check_size_t_mul(dictionaryCount, sizeof(CFPropertyListRef), &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
STACK_BUFFER_DECL(CFPropertyListRef, buffer, dictionaryCount <= 256 ? dictionaryCount : 1);
list = (dictionaryCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, byte_cnt, __kCFAllocatorGCScannedMemory);
if (!list) FAIL_FALSE;
Boolean madeSet = false;
if (!set && 15 < curDepth) {
set = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
madeSet = set ? true : false;
}
if (set) CFSetAddValue(set, (const void *)(uintptr_t)startOffset);
if (keyPaths) {
// Only get a subset of this dictionary
CFSetRef theseKeys, nextKeys;
__CFPropertyListCreateSplitKeypaths(kCFAllocatorSystemDefault, keyPaths, &theseKeys, &nextKeys);
Boolean success = true;
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(allocator, CFSetGetCount(theseKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (theseKeys) {
CFTypeRef *keys = (CFTypeRef *)malloc(CFSetGetCount(theseKeys) * sizeof(CFTypeRef));
CFSetGetValues(theseKeys, keys);
for (CFIndex i = 0; i < CFSetGetCount(theseKeys); i++) {
CFStringRef key = (CFStringRef)keys[i];
uint64_t keyOffset, valueOffset;
Boolean found = __CFBinaryPlistGetOffsetForValueFromDictionary3(databytes, datalen, startOffset, trailer, key, &keyOffset, &valueOffset, false, objects);
if (found) {
CFPropertyListRef result;
success = __CFBinaryPlistCreateObjectFiltered(databytes, datalen, valueOffset, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, nextKeys, &result);
if (success) {
CFDictionarySetValue(dict, key, result);
CFRelease(result);
} else {
break;
}
}
}
free(keys);
CFRelease(theseKeys);
}
if (nextKeys) CFRelease(nextKeys);
if (success) {
if (!(mutabilityOption == kCFPropertyListMutableContainers || mutabilityOption == kCFPropertyListMutableContainersAndLeaves)) {
// make immutable
*plist = CFDictionaryCreateCopy(allocator, dict);
CFRelease(dict);
} else {
*plist = dict;
}
} else if (dict) {
CFRelease(dict);
}
} else {
for (CFIndex idx = 0; idx < dictionaryCount; idx++) {
CFPropertyListRef pl = NULL;
off = _getOffsetOfRefAt(databytes, ptr, trailer);
if (!__CFBinaryPlistCreateObjectFiltered(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, NULL, &pl) || (idx < dictionaryCount / 2 && !_plistIsPrimitive(pl))) {
if (pl && !(0)) CFRelease(pl);
while (idx--) {
CFRelease(list[idx]);
}
if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
if (madeSet) { CFRelease(set); }
FAIL_FALSE;
}
__CFAssignWithWriteBarrier((void **)list + idx, (void *)pl);
ptr += trailer->_objectRefSize;
}
if (mutabilityOption != kCFPropertyListImmutable) {
*plist = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
for (CFIndex idx = 0; idx < dictionaryCount / 2; idx++) {
CFDictionaryAddValue((CFMutableDictionaryRef)*plist, list[idx], list[idx + dictionaryCount / 2]);
}
for (CFIndex idx = 0; idx < dictionaryCount; idx++) {
CFRelease(list[idx]);
}
} else {
if (!kCFUseCollectableAllocator) {
*plist = __CFDictionaryCreateTransfer(allocator, list, list + dictionaryCount / 2, dictionaryCount / 2);
} else {
*plist = CFDictionaryCreate(allocator, list, list + dictionaryCount / 2, dictionaryCount / 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
for (CFIndex idx = 0; idx < dictionaryCount; idx++) {
CFRelease(list[idx]);
}
}
}
}
if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
if (madeSet) {
CFRelease(set);
set = NULL;
}
if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list);
return (*plist) ? true : false;
}
}
FAIL_FALSE;
}