Open Shelf…

Ooops, another bug in BackRow

Recursive functions are great. They’re a very useful tool for a great many things, and in the BackRow framework’s RUIPreferenceManager class, they’re put to (presumably) good use when handling preference domains. There’s a single funnel function which uses CFPreferencesCopyAppValue() to fetch a preference from a given domain/app; if unable to find a value, it splits the domain, removes the last component (provided it’s got more than two components here) and then calls itself again with this new, shorter domain.

That in itself is not a problem. The implementation, however, has one small flaw that will at least throw an exception, and at worst cause a crash. See if you can find it:

- (id) _valueForKey: (NSString *) key forDomain: (NSString *) domain
{
    [_preferencesLock lock];
    id result = (id) CFPreferencesCopyAppValue( (CFStringRef)key, (CFStringRef)domain );
    [_preferencesLock unlock];

    if ( result == nil )
    {
        NSMutableArray * components = [NSMutableArray arrayWithArray: 
            [domain componentsSeparatedByString: @"."]];
        unsigned count = [components count];

        if ( (count == 0) || (count <= 2) )
        {
            [components removeLastObject];
            result = [self _valueForKey: key 
                              forDomain: [components componentsJoinedByString: @"."]];
        }
    }

    return ( [result autorelease] );
}

Yes, that’s right. The recursive call will return an autoreleased object. Which then gets autoreleased once more.

Oops. Time for another software update there ;)

No Responses

Note that comments are displayed in reverse chronological order with topmost comments being freshest. Subscribe | Comment

Leave a Reply

You must be logged in to post a comment.