[Checkins] [zopefoundation/BTrees] a88cb9: Don't allow to pass bad child into tree.__setstate...

Kirill Smelkov noreply at github.com
Fri May 29 19:13:31 CEST 2020


  Branch: refs/heads/master
  Home:   https://github.com/zopefoundation/BTrees
  Commit: a88cb9de849e037b097e74fdc621332c2dd66698
      https://github.com/zopefoundation/BTrees/commit/a88cb9de849e037b097e74fdc621332c2dd66698
  Author: Kirill Smelkov <kirr at nexedi.com>
  Date:   2020-05-29 (Fri, 29 May 2020)

  Changed paths:
    M BTrees/BTreeTemplate.c
    M BTrees/_base.py
    M BTrees/tests/common.py
    M BTrees/tests/test__base.py
    M CHANGES.rst

  Log Message:
  -----------
  Don't allow to pass bad child into tree.__setstate__ to avoid memory corruption and crash

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




More information about the checkins mailing list