X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/6b200bc335dc93c5516ccb52f14bd896d8c7fad7..07691282a056c4efea71e1e505527601e8cc166b:/OSX/libsecurity_transform/lib/Transform.cpp?ds=inline diff --git a/OSX/libsecurity_transform/lib/Transform.cpp b/OSX/libsecurity_transform/lib/Transform.cpp index eea4a673..a9d1fc7c 100644 --- a/OSX/libsecurity_transform/lib/Transform.cpp +++ b/OSX/libsecurity_transform/lib/Transform.cpp @@ -28,17 +28,17 @@ static char RandomChar() } -static CFStringRef ah_set_describe(const void *v) { +static CFStringRef ah_set_describe(const void *v) CF_RETURNS_RETAINED { transform_attribute *ta = ah2ta(static_cast(const_cast(v))); return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@=%@ (conn: %@)"), ta->transform->GetName(), ta->name, ta->value ? ta->value : CFSTR("NULL"), ta->connections ? static_cast(ta->connections) : static_cast(CFSTR("NONE"))); } -static CFStringRef AttributeHandleFormat(CFTypeRef ah, CFDictionaryRef dict) { +static CFStringRef AttributeHandleFormat(CFTypeRef ah, CFDictionaryRef dict) CF_RETURNS_RETAINED { transform_attribute *ta = ah2ta(ah); return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@"), ta->transform->GetName(), ta->name); } -static CFStringRef AttributeHandleDebugFormat(CFTypeRef ah) { +static CFStringRef AttributeHandleDebugFormat(CFTypeRef ah) CF_RETURNS_RETAINED { transform_attribute *ta = ah2ta(ah); return CFStringCreateWithFormat(NULL, NULL, CFSTR("%@/%@ (%p)"), ta->transform->GetName(), ta->name, ta); } @@ -61,14 +61,14 @@ static void AttributeHandleFinalize(CFTypeRef ah) if (ta->value) { - CFRelease(ta->value); + CFReleaseNull(ta->value); } // ta->q already released if (ta->connections) { - CFRelease(ta->connections); + CFReleaseNull(ta->connections); } if (ta->semaphore) @@ -117,7 +117,7 @@ SecTransformAttributeRef Transform::makeAH(transform_attribute *ta) { static pthread_key_t ah_search_key_slot; static void destroy_ah_search_key(void *ah) { - CFRelease(ah); + CFReleaseNull(ah); pthread_setspecific(ah_search_key_slot, NULL); } @@ -198,7 +198,7 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri CFSetAddValue(mAttributes, ah); if (CFSetGetCount(mAttributes) != cnt+1) { - CFRelease(ta->name); + CFReleaseNull(ta->name); free(ta); return NULL; } @@ -209,7 +209,7 @@ SecTransformAttributeRef Transform::getAH(SecTransformStringOrAttributeRef attri CFStringGetBytes(qname, CFRangeMake(0, CFStringGetLength(qname)), kCFStringEncodingUTF8, '?', FALSE, qnbuf, sz, &used); qnbuf[used] = '\0'; ta->q = dispatch_queue_create((char*)qnbuf, NULL); - CFRelease(qname); + CFReleaseNull(qname); ta->semaphore = dispatch_semaphore_create(kMaxPendingTransactions); @@ -265,7 +265,12 @@ bool Transform::HasNoOutboundConnections() { // make an array big enough to hold all of the attributes CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute* attributes[numAttributes]; + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + + if (attributes == NULL) { + // No more memory, we assume it's orphaned + return true; + } TAGetAll(attributes); @@ -275,10 +280,13 @@ bool Transform::HasNoOutboundConnections() { if (attributes[i]->connections && CFArrayGetCount(attributes[i]->connections) != 0) { + free(attributes); return false; } } + free(attributes); + return true; } @@ -288,7 +296,12 @@ bool Transform::HasNoInboundConnections() { // make an array big enough to hold all of the attributes CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute* attributes[numAttributes]; + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + + if (attributes == NULL) { + // No more memory, we assume it's orphaned + return true; + } TAGetAll(attributes); @@ -298,10 +311,13 @@ bool Transform::HasNoInboundConnections() { if (attributes[i]->has_incoming_connection) { + free(attributes); return false; } } + free(attributes); + return true; } @@ -375,7 +391,7 @@ Transform::Transform(CFStringRef transformType, CFStringRef CFobjectType) : ta->ignore_while_externalizing = 1; CFStringRef attributeName = CFStringCreateWithCStringNoCopy(NULL, name, 0, kCFAllocatorMalloc); SetAttributeNoCallback(kSecTransformTransformName, attributeName); - CFRelease(attributeName); + CFReleaseNull(attributeName); free(dqName); free(aqName); @@ -413,8 +429,14 @@ void Transform::FinalizePhase2() void Transform::FinalizeForClang() { CFIndex numAttributes = CFSetGetCount(mAttributes); - SecTransformAttributeRef handles[numAttributes]; - CFSetGetValues(mAttributes, (const void**)&handles); + SecTransformAttributeRef *handles = (const void**)malloc(numAttributes*sizeof(SecTransformAttributeRef)); + + if (handles == NULL) { + syslog(LOG_ERR, "Unable to allocate SecTransformAttributeRef handles in FinalizeForClang"); + return; + } + + CFSetGetValues(mAttributes, handles); for(CFIndex i = 0; i < numAttributes; ++i) { SecTransformAttributeRef ah = handles[i]; @@ -423,7 +445,7 @@ void Transform::FinalizeForClang() set_dispatch_finalizer(ta->q, ^{ // NOTE: not done until all pending use of the attribute queue has ended AND retain count is zero ta->transform = NULL; - CFRelease(ah); + CFReleaseSafe(ah); }); // If there is a pending pushback the attribute queue will be suspended, and needs a kick before it can be destructed. if (__sync_bool_compare_and_swap(&ta->pushback_state, transform_attribute::pb_value, transform_attribute::pb_discard)) { @@ -431,7 +453,7 @@ void Transform::FinalizeForClang() } dispatch_release(ta->q); } - + // We might be finalizing a transform as it is being activated, make sure that is complete before we do the rest dispatch_group_notify(mActivationPending, mDispatchQueue, ^{ if (mActivationQueue != NULL) { @@ -446,6 +468,8 @@ void Transform::FinalizeForClang() }); dispatch_release(mDispatchQueue); }); + + free(handles); } void Transform::Finalize() @@ -474,25 +498,25 @@ void Transform::Finalize() Transform::~Transform() { - CFRelease(mAttributes); + CFReleaseNull(mAttributes); if (mAbortError) { - CFRelease(mAbortError); + CFReleaseNull(mAbortError); mAbortError = NULL; } // See if we can catch anything using us after our death mDispatchQueue = (dispatch_queue_t)0xdeadbeef; - CFRelease(mTypeName); + CFReleaseNull(mTypeName); if (NULL != mPushedback) { - CFRelease(mPushedback); + CFReleaseNull(mPushedback); } dispatch_release(mActivationPending); } -CFStringRef Transform::GetName() { +CFStringRef Transform::GetName() CF_RETURNS_NOT_RETAINED { return (CFStringRef)GetAttribute(kSecTransformTransformName); } @@ -599,14 +623,14 @@ CFErrorRef Transform::RefactorErrorToIncludeAbortingTransform(CFErrorRef sourceE CFStringRef domain = CFErrorGetDomain(sourceError); CFDictionaryRef oldUserInfo = CFErrorCopyUserInfo(sourceError); CFMutableDictionaryRef userInfo = CFDictionaryCreateMutableCopy(NULL, 0, oldUserInfo); - CFRelease(oldUserInfo); + CFReleaseNull(oldUserInfo); // add the new key and value to the dictionary CFDictionaryAddValue(userInfo, kSecTransformAbortOriginatorKey, GetCFObject()); // make a new CFError CFErrorRef newError = CFErrorCreate(NULL, domain, code, userInfo); - CFRelease(userInfo); + CFReleaseNull(userInfo); return newError; } @@ -627,7 +651,7 @@ void Transform::AbortJustThisTransform(CFErrorRef abortErr) // by the dispatch queue finalizer so we don't need a retain/release of // abortErr for the abortAction block, but we do need to retain it // here to match with the release by the destructor. - CFRetain(abortErr); + CFRetainSafe(abortErr); dispatch_block_t abortAction = ^{ // This actually makes the abort happen, it needs to run on the transform's queue while the @@ -674,14 +698,18 @@ void Transform::AbortAllTransforms(CFTypeRef err) if (CFGetTypeID(err) != CFErrorGetTypeID()) { - replacementErr = err = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "ABORT set to a %@ (%@) not a %@", CFCopyTypeIDDescription(CFGetTypeID(err)), err, CFCopyTypeIDDescription(CFErrorGetTypeID())); + CFStringRef thisErrorTypeDescription = CFCopyTypeIDDescription(CFGetTypeID(err)); + CFStringRef regularErrorTypeDescription = CFCopyTypeIDDescription(CFErrorGetTypeID()); + replacementErr = err = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "ABORT set to a %@ (%@) not a %@", thisErrorTypeDescription, err, regularErrorTypeDescription); + CFReleaseNull(thisErrorTypeDescription); + CFReleaseNull(regularErrorTypeDescription); } error = RefactorErrorToIncludeAbortingTransform((CFErrorRef)err); if (replacementErr) { - CFRelease(replacementErr); + CFReleaseNull(replacementErr); } GroupTransform *root = GetRootGroup(); @@ -693,7 +721,7 @@ void Transform::AbortAllTransforms(CFTypeRef err) t->AbortJustThisTransform(error); }); dispatch_group_notify(all_aborted, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void) { - CFRelease(error); + CFReleaseSafe(error); dispatch_release(all_aborted); }); } @@ -871,10 +899,10 @@ CFErrorRef Transform::SetAttributeNoCallback(SecTransformStringOrAttributeRef ke if (ta->value != value) { if (value && !doNotRetain) { - CFRetain(value); + CFRetainSafe(value); } if (ta->value) { - CFRelease(ta->value); + CFReleaseNull(ta->value); } } @@ -947,7 +975,9 @@ CFErrorRef Transform::SetAttribute(CFTypeRef key, CFTypeRef value) { if (mAbortError) { - return CreateSecTransformErrorRef(kSecTransformErrorAborted, "ABORT has been sent to the transform (%@)", mAbortError); + CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorAborted, "ABORT has been sent to the transform (%@)", mAbortError); + CFAutorelease(result); + return result; } // queue up the setting of the key and value @@ -961,32 +991,27 @@ CFErrorRef Transform::SetAttribute(CFTypeRef key, CFTypeRef value) ah = getAH(static_cast(key)); if (!ah) { - return CreateSecTransformErrorRef(kSecTransformErrorUnsupportedAttribute, "Can't set attribute %@ in transform %@", key, GetName()); + CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorUnsupportedAttribute, "Can't set attribute %@ in transform %@", key, GetName()); + CFAutorelease(result); + return result; } } else { - return CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "Transform::SetAttribute called with %@, requires a string or an AttributeHandle", key); + CFErrorRef result = CreateSecTransformErrorRef(kSecTransformErrorInvalidType, "Transform::SetAttribute called with %@, requires a string or an AttributeHandle", key); + CFAutorelease(result); + return result; } // Do this after the error check above so we don't leak - if (value != NULL) - { - CFRetain(value); // if we use dispatch_async we need to own the value (the matching release is in the set block) - } - + CFRetainSafe(value); // if we use dispatch_async we need to own the value (the matching release is in the set block) transform_attribute *ta = ah2ta(ah); dispatch_block_t set = ^{ Do(ah, value); - dispatch_semaphore_signal(ta->semaphore); - - if (value != NULL) - { - CFRelease(value); - } + CFReleaseSafe(value); }; @@ -1062,7 +1087,7 @@ CFErrorRef Transform::Pushback(SecTransformAttributeRef ah, CFTypeRef value) } if (value) { - CFRetain(value); + CFRetainSafe(value); } ta->pushback_value = value; dispatch_suspend(ta->q); @@ -1094,7 +1119,7 @@ void Transform::try_pushbacks() { Do(ah, v); if (v) { - CFRelease(v); + CFReleaseNull(v); } if (ta->pushback_state == transform_attribute::pb_repush) { ta->pushback_state = transform_attribute::pb_empty; @@ -1106,7 +1131,7 @@ void Transform::try_pushbacks() { dispatch_resume(ta->q); } - CFRelease(pb); + CFReleaseNull(pb); if (succeeded && CFArrayGetCount(mPushedback)) { // some attribute changed while we proceeded the last batch of pushbacks, so any "new" pushbacks are eligible to run again. @@ -1130,7 +1155,7 @@ void Transform::Debug(const char *cfmt, ...) { CFURLRef p = CFURLCreateWithFileSystemPath(NULL, CFSTR("/dev/stderr"), kCFURLPOSIXPathStyle, FALSE); StdErrWriteStream = CFWriteStreamCreateWithFile(NULL, p); CFWriteStreamOpen(StdErrWriteStream); - CFRelease(p); + CFReleaseNull(p); }); out = StdErrWriteStream; } @@ -1140,7 +1165,7 @@ void Transform::Debug(const char *cfmt, ...) { CFStringRef fmt = CFStringCreateWithCString(NULL, cfmt, kCFStringEncodingUTF8); CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, ap); - CFRelease(fmt); + CFReleaseNull(fmt); va_end(ap); @@ -1171,7 +1196,7 @@ void Transform::Debug(const char *cfmt, ...) { } }); - CFRelease(str); + CFReleaseNull(str); } } @@ -1252,7 +1277,7 @@ CFTypeRef Transform::Execute(dispatch_queue_t deliveryQueue, SecMessageBlock del if (isFinal) { dispatch_async(this->mDispatchQueue, ^{ - CFRelease(g); + CFReleaseSafe(g); }); } }; @@ -1261,7 +1286,7 @@ CFTypeRef Transform::Execute(dispatch_queue_t deliveryQueue, SecMessageBlock del if (!deliveryBlock) { - CFRelease(g); + CFReleaseNull(g); } return ret; @@ -1279,7 +1304,7 @@ CFTypeRef Transform::Execute(dispatch_queue_t deliveryQueue, SecMessageBlock del // Do a retain on our parent since we are using it GroupTransform *rootGroup = GetRootGroup(); - CFRetain(rootGroup->GetCFObject()); + CFRetainSafe(rootGroup->GetCFObject()); CFTypeRef result = NULL; @@ -1311,8 +1336,8 @@ CFTypeRef Transform::Execute(dispatch_queue_t deliveryQueue, SecMessageBlock del // It is safe to keep the monitors attached, because it is invalid to try to execute again, BUT // we do need to release the reference to the group that the monitor would normally release // when it processes the final message. - CFRelease(rootGroup->GetCFObject()); - CFRelease(monitorRef); + CFReleaseSafe(rootGroup->GetCFObject()); + CFReleaseNull(monitorRef); rootGroup->StartedExecutionInGroup(false); return NULL; } @@ -1335,7 +1360,7 @@ CFTypeRef Transform::Execute(dispatch_queue_t deliveryQueue, SecMessageBlock del dispatch_group_notify(activated, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_release(activated); // once we have been activated (but not before!), the monitor belongs to the group, and we can drop our claim - CFRelease(monitorRef); + CFReleaseSafe(monitorRef); rootGroup->StartedExecutionInGroup(true); }); }); @@ -1411,8 +1436,8 @@ CFErrorRef Transform::ExecuteOperation(CFStringRef &outputAttached, SecMonitorRe if (still_need) { CFStringRef elist = CFStringCreateByCombiningStrings(NULL, still_need, CFSTR(", ")); CFErrorRef err = CreateSecTransformErrorRef(kSecTransformErrorMissingParameter, "Can not execute %@, missing required attributes: %@", GetName(), elist); - CFRelease(elist); - CFRelease(still_need); + CFReleaseNull(elist); + CFReleaseNull(still_need); return err; } @@ -1514,17 +1539,11 @@ bool Transform::IsExternalizable() } static const void *CFTypeOrNULLRetain(CFAllocatorRef allocator, const void *value) { - if (value != NULL) { - return CFRetain(value); - } else { - return value; - } + return CFRetainSafe(value); } static void CFTypeOrNULLRelease(CFAllocatorRef allocator, const void *value) { - if (value != NULL) { - CFRelease(value); - } + CFReleaseNull(value); } static CFStringRef CFTypeOrNULLCopyDescription (const void *value) { @@ -1593,7 +1612,7 @@ CFDictionaryRef Transform::GetAHDictForSaveState(SecTransformStringOrAttributeRe for(i = 0; i < cnt; ++i) { - CFRelease(keys[i]); + CFReleaseNull(keys[i]); } return ret; @@ -1603,9 +1622,17 @@ CFDictionaryRef Transform::GetAHDictForSaveState(SecTransformStringOrAttributeRe CFDictionaryRef Transform::CopyState() { CFIndex i, j, cnt = CFSetGetCount(mAttributes); - transform_attribute *attrs[cnt]; - CFStringRef names[cnt]; - CFDictionaryRef values[cnt]; + transform_attribute **attrs = (transform_attribute**)malloc(cnt*sizeof(transform_attribute)); + CFStringRef *names = (CFStringRef*)malloc(cnt*sizeof(CFStringRef)); + CFDictionaryRef *values = (CFDictionaryRef*)malloc(sizeof(CFDictionaryRef) * cnt); + + if (attrs == NULL || names == NULL || values == NULL) { + free(attrs); + free(names); + free(values); + return NULL; + } + TAGetAll(attrs); for(i = j = 0; i < cnt; ++i) { @@ -1618,16 +1645,20 @@ CFDictionaryRef Transform::CopyState() } CFDictionaryRef result = CFDictionaryCreate(NULL, (const void**)&names, (const void**)&values, j, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - + + free(names); + for(i = j = 0; i < cnt; ++i) { transform_attribute *ta = attrs[i]; if (!ta->ignore_while_externalizing) { - CFRelease(values[j++]); + CFReleaseNull(values[j++]); } } + free(attrs); + free(values); return result; } @@ -1673,18 +1704,12 @@ void Transform::RestoreState(CFDictionaryRef state) else { CFErrorRef result = SendMetaAttribute(ah, (SecTransformMetaAttributeType)t, meta_values[j]); - if (result) - { - CFRelease(result); // see Transform::RestoreState is ignoring error returns - } + CFReleaseNull(result); // see Transform::RestoreState is ignoring error returns } } CFErrorRef result = SendMetaAttribute(ah, kSecTransformMetaAttributeExternalize, kCFBooleanTrue); - if (result) - { - CFRelease(result); // see Transform::RestoreState is ignoring error returns - } + CFReleaseNull(result); // see Transform::RestoreState is ignoring error returns } } @@ -1737,6 +1762,7 @@ CFDictionaryRef Transform::Externalize(CFErrorRef* error) // Really? This just seems like a bad idea if (NULL != error) { + CFRetainSafe(err); *error = err; } return NULL; @@ -1749,8 +1775,8 @@ CFDictionaryRef Transform::Externalize(CFErrorRef* error) CFDictionaryAddValue(output, EXTERN_TRANSFORM_CONNECTION_ARRAY, connections); // clean up - CFRelease(connections); - CFRelease(transforms); + CFReleaseNull(connections); + CFReleaseNull(transforms); return output; } @@ -1772,28 +1798,33 @@ CFErrorRef Transform::ProcessExternalize(CFMutableArrayRef transforms, CFMutable CFTypeRef type = CFStringCreateCopy(NULL, mTypeName); CFDictionaryAddValue(node, EXTERN_TRANSFORM_TYPE, type); - CFRelease(type); + CFReleaseNull(type); if (state != NULL) { CFDictionaryAddValue(node, EXTERN_TRANSFORM_STATE, state); - CFRelease(state); + CFReleaseNull(state); } CFDictionaryRef customItems = GetCustomExternalData(); if (NULL != customItems) { CFDictionaryAddValue(node, EXTERN_TRANSFORM_CUSTOM_EXPORTS_DICTIONARY, customItems); - CFRelease(customItems); + CFReleaseNull(customItems); } // append the resulting dictionary to the node list CFArrayAppendValue(transforms, node); - CFRelease(node); + CFReleaseNull(node); // now walk the attribute list CFIndex numAttributes = CFSetGetCount(mAttributes); - transform_attribute *attributes[numAttributes]; + transform_attribute **attributes = (transform_attribute**)malloc(numAttributes*sizeof(transform_attribute)); + + if (attributes == NULL) { + return GetNoMemoryErrorAndRetain(); + } + TAGetAll(attributes); CFIndex i; @@ -1824,10 +1855,12 @@ CFErrorRef Transform::ProcessExternalize(CFMutableArrayRef transforms, CFMutable CFDictionaryAddValue(connection, EXTERN_TRANSFORM_TO_ATTRIBUTE, ta->name); CFArrayAppendValue(connections, connection); - CFRelease(connection); + CFReleaseNull(connection); } } } + free(attributes); + return NULL; }