Skip to content

binary_heap::PeekMut does not need "leak amplification" #146817

@cpud36

Description

@cpud36

Context

The BinaryHeap from alloc crate has handy method peek_mut, which allows to look at the top element in the heap, and possible mutate it, without removing it from the heap. This mutation however can alter the element order relative to other elements, and the heap needs to be adjusted. To handle this, the PeekMut tracks if it has ever exposed a &mut T access via DerefMut. If &mut T was ever exposed, PeekMut adjusts the heap in its Drop implementation.

Leak amplification

This works well, unless the user leaks the PeekMut(e.g. via mem::forget, or via Rc cycle). Then the Drop of PeekMut never runs and we get the heap with an incorrect ordering of elements.

To cope with this possible leakage, the PeekMut uses a well-known technique called "leak amplification". That is, PeekMut uses Vec::set_len to forget about all other elements in the heap, when first &mut T is acquired, and then restores vector len when drop is run. So if the user leaks the PeekMut, we still have the valid heap (although, it has only 1 element - all others were forgotten forever).

This change was introduced in commit aedb756.

Problem

The "leak amplification" technique is inteded to avoid memory corruption. It is often used when the type creates temporary holes in the container. Thus, forgetting to fixup those holes might lead to double free, or use after free. In other words, leak amplification is used to make the code sound, not to make it logically correct.

However BinaryHeap soundness does not depend on correctness of element ordering. BinaryHeap will continue to be sound(that is no memory issues), even the elements in the underlying vector get shuffled in arbitrary way. This is easy to see, as there can be an incorrect Ord implementation; or users can use interior mutability to break the heap ordering.

The data structure will not work logically correct in such case, but it is the question of which correctness property we are willing to sacrafice: ordering of the elements or elements leakage.

Proposal

I propose to rollback the before mentioned commit and ignore the leakage problem in the PeekMut.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions