Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Unreliable image cache due to hash collisions #28

Closed
deresov opened this issue Aug 19, 2014 · 3 comments
Closed

Unreliable image cache due to hash collisions #28

deresov opened this issue Aug 19, 2014 · 3 comments
Assignees
Milestone

Comments

@deresov
Copy link

deresov commented Aug 19, 2014

In "FSImageLoader.m" on line 79 [NSString hash] method is used to create a cache key:

NSString *cacheKey = [NSString stringWithFormat:@"FSImageLoader-%lu", (unsigned long)[[aURL description] hash]];

This causes problems with long image URLs, because "hash" method of NSString only uses 96 characters to generate the hash (first 32, last 32 and middle 32). Basically if your URLs are over 96 chars in length, there is a good chance of getting the same cacheKey for two different URLs. I run into this problem because I had a bunch of long, similar URLs where the only difference was the product id (starting at char 39).

This article describes the problem in detail.

Would it be possible to use a more robust hash function? Here is an implementation using MD5 hash:

- (NSString *)getMD5ValueForURL:(NSURL*)aURL {
    const char *urlString = [[aURL absoluteString] UTF8String];
    unsigned char hashBytes[CC_MD5_DIGEST_LENGTH];
    CC_MD5(urlString, strlen(urlString), hashBytes);

    NSMutableString *hashString = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for ( NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++ ) {
        [hashString appendFormat:@"%02x", hashBytes[i]];
    }

    return hashString;
}
@x2on x2on added this to the 2.7 milestone Aug 26, 2014
@x2on x2on self-assigned this Aug 26, 2014
@x2on
Copy link
Owner

x2on commented Sep 2, 2014

Im currently thinking about the migration scenario.

Does this solution help you?

    NSString *cacheKey = [NSString stringWithFormat:@"FSImageLoader-%@", [[[aURL absoluteString] copy] SHA1]];
    UIImage *anImage = [[EGOCache globalCache] imageForKey:cacheKey];

    if (!anImage) {
        // Deprecated cacheKey
        NSString *deprecatedCacheKey = [NSString stringWithFormat:@"FSImageLoader-%lu", (unsigned long) [[aURL description] hash]];
        anImage = [[EGOCache globalCache] imageForKey:deprecatedCacheKey];
    }

@deresov
Copy link
Author

deresov commented Sep 11, 2014

This would definitely work. Thanks for a great library!

@x2on x2on closed this as completed in 9b3808b Feb 22, 2015
@x2on
Copy link
Owner

x2on commented Feb 22, 2015

Sorry for the delay - is now in version 3.0

@x2on x2on modified the milestones: 3.0, 2.7 Feb 22, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants