CF_PRIVATE bool __CFBinaryPlistCreateObjectFiltered()

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;
}