• antirez's avatar
    dict.c iterator API misuse protection. · 4a005a2a
    antirez authored
    dict.c allows the user to create unsafe iterators, that are iterators
    that will not touch the dictionary data structure in any way, preventing
    copy on write, but at the same time are limited in their usage.
    
    The limitation is that when itearting with an unsafe iterator, no call
    to other dictionary functions must be done inside the iteration loop,
    otherwise the dictionary may be incrementally rehashed resulting into
    missing elements in the set of the elements returned by the iterator.
    
    However after introducing this kind of iterators a number of bugs were
    found due to misuses of the API, and we are still finding
    bugs about this issue. The bugs are not trivial to track because the
    effect is just missing elements during the iteartion.
    
    This commit introduces auto-detection of the API misuse. The idea is
    that an unsafe iterator has a contract: from initialization to the
    release of the iterator the dictionary should not change.
    
    So we take a fingerprint of the dictionary state, xoring a few important
    dict properties when the unsafe iteartor is initialized. We later check
    when the iterator is released if the fingerprint is still the same. If it
    is not, we found a misuse of the iterator, as not allowed API calls
    changed the internal state of the dictionary.
    
    This code was checked against a real bug, issue #1240.
    
    This is what Redis prints (aborting) when a misuse is detected:
    
    Assertion failed: (iter->fingerprint == dictFingerprint(iter->d)),
    function dictReleaseIterator, file dict.c, line 587.
    4a005a2a
dict.c 25.2 KB