Skip to content

Failing to drop HeaderMap::Drain causes double-free #354

@Qwaz

Description

@Qwaz

http/src/header/map.rs

Lines 2115 to 2122 in 9c05e39

unsafe {
let entry = &(*self.map).entries[idx];
// Read the header name
key = ptr::read(&entry.key as *const _);
value = ptr::read(&entry.value as *const _);
next = entry.links.map(|l| l.next);
};

http/src/header/map.rs

Lines 2140 to 2148 in 9c05e39

impl<'a, T> Drop for Drain<'a, T> {
fn drop(&mut self) {
unsafe {
let map = &mut *self.map;
debug_assert!(map.extra_values.is_empty());
map.entries.set_len(0);
}
}
}

Failing to drop a value is considered safe in Rust, and unsafe code should not rely on this behavior.

It is reasonable for safe code to assume that destructor leaks do not happen, as any program that leaks destructors is probably wrong. However unsafe code cannot rely on destructors to be run in order to be safe.

HeaderMap::Drain uses ptr::read to move out entries from the map when it iterates, and calls map.entries.set_len(0) to clear the map at once when it is dropped. If Drain's drop is not called, double-free happens when HeaderMap is dropped. Also, if Drain is dropped without iterating to the end, it leaks memory.

Demonstration

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