• Kirill Smelkov's avatar
    Don't allow to pass bad child into tree.__setstate__ to avoid memory corruption and crash · a88cb9de
    Kirill Smelkov authored
    Hello up there. To test my module that computes diff for BTrees I was playing
    with manually creating BTrees with different topologies[1,2] and hit the
    following bug that was leading to segmentation faults:
    
    C implementation of Tree.__setstate__ allows to pass in arbitrary objects in
    place of children and casts child to (Bucket*) if child type is not type of the
    tree
    
        _without further checking that type of the child is actually Bucket_
    
    This leads to crashes when later the code, that is accessing tree nodes,
    goes to leafs, accesses passed in objects assuming they are buckets with
    corresponding C-level Bucket structure layout, and oops dereferences e.g.
    Bucket->keys, or Bucket->values from memory initialized via non-Bucket
    C-level data.
    
    -> Fix it by allowing to pass into tree.__setstate__ only children of
    either tree or bucket types.
    
    Note: for tree kind the type is checked exactly, because in many places C
    implementation already does `if (SameType_Check(tree, X))` and assumes X is
    of bucket kind if that check fails. For buckets we accept tree._bucket_type
    subclasses as they are handled correctly and bucket type for tree.firstbucket
    is already verified via "isinstance".
    
    Kirill
    
    P.S.
    
    test___setstate___to_multiple_buckets is adjusted to avoid test failures
    because Test_Tree._makeOne() was creating tree with ._bucket_type different
    from _Bucket defined in that test.
    
    [1] https://lab.nexedi.com/kirr/wendelin.core/blob/28010b7/wcfs/internal/xbtree.py
    [2] https://lab.nexedi.com/kirr/wendelin.core/blob/28010b7/wcfs/internal/xbtree_test.py
    
    /helped-by @jamadden
    a88cb9de
To find the state of this project's repository at the time of any of these versions, check out the tags.
CHANGES.rst 10.8 KB