diff --git a/Source/CFTree.c b/Source/CFTree.c index 96e93c79..a25d5bde 100644 --- a/Source/CFTree.c +++ b/Source/CFTree.c @@ -73,7 +73,7 @@ CFTreeFinalize (CFTypeRef cf) release = tree->_context.release; if (release) - release (tree); + release (tree->_context.info); } static CFRuntimeClass CFTreeClass = @@ -116,6 +116,9 @@ CFTreeCreate (CFAllocatorRef allocator, const CFTreeContext *context) if (context == NULL) context = &_kCFNullTreeContext; memcpy (&new->_context, context, sizeof(CFTreeContext)); + if (new->_context.retain) + new->_context.info = + (void *)new->_context.retain (new->_context.info); } return new; diff --git a/Tests/CFTree/context.m b/Tests/CFTree/context.m new file mode 100644 index 00000000..25b9a4f3 --- /dev/null +++ b/Tests/CFTree/context.m @@ -0,0 +1,36 @@ +#include +#include + +#include "../CFTesting.h" + +int main (void) +{ + CFStringRef info; + CFTreeContext ctx; + CFTreeContext out; + CFTreeRef tree; + + info = CFStringCreateWithCString (NULL, "node", kCFStringEncodingUTF8); + + ctx.version = 0; + ctx.info = (void *)info; + ctx.retain = CFRetain; + ctx.release = CFRelease; + ctx.copyDescription = CFCopyDescription; + + tree = CFTreeCreate (NULL, &ctx); + PASS_CF(tree != NULL, "Created a tree with a retaining context."); + + CFTreeGetContext (tree, &out); + PASS_CF(out.info == (void *)info, "CFTreeGetContext returns the info."); + PASS_CF(out.retain == CFRetain && out.release == CFRelease, + "CFTreeGetContext returns the context callbacks."); + + CFRelease (tree); + PASS_CF(CFStringGetLength (info) == 4, + "The context info outlives the tree that retained it."); + + CFRelease (info); + + return 0; +}