Skip to content

Dropping Objects Created with IdMap::from_iter May Free Uninitialized Memory #4

@GeorgeAndrou

Description

@GeorgeAndrou

Hello,

We are @purseclab, and we are fuzzing Rust crates to identify memory violation bugs. While analyzing this crate, we discovered that objects created with the IdMap::from_iter constructor may lead to deallocation of uninitialized memory.

The PoC below triggers a segmentation fault.

PoC:

#![forbid(unsafe_code)]

use id_map::*;
struct CustomType0(String);


fn main() {
    let mut entries = Vec::new();
    entries.push(CustomType0(String::from("Hello")));
    entries.push(CustomType0(String::from("World")));
    let _ = IdMap::from_iter(entries);
}

Bug Description:

The function IdMap::from_iter (see line 431) uses the capacity of the values vector to initialize the ids field of the resulting IdMap object.

id-map/src/lib.rs

Lines 425 to 438 in a2fa8d4

impl<T> FromIterator<T> for IdMap<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut values = Vec::from_iter(iter);
unsafe { values.set_len(0) }
let space = values.capacity();
let ids = IdSet::new_filled(values.capacity());
IdMap {
values,
space,
ids,
}
}
}

When the IdMap is dropped, the drop_values method is invoked to deallocate each element in the ids field.

id-map/src/lib.rs

Lines 326 to 330 in a2fa8d4

unsafe fn drop_values(&mut self) {
for id in &self.ids {
ptr::drop_in_place(self.values.get_unchecked_mut(id))
}
}

However, drop_values iterates over ids and uses each id as an index into the values vector.
If values.len() < values.capacity(), then id may exceed the length of values, resulting in an attempt to drop uninitialized memory, leading to undefined behavior and a segmentation fault.

Output:

AddressSanitizer:DEADLYSIGNAL
=================================================================
==647802==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x55a827600582 bp 0x000000000000 sp 0x7fff36f1d9c0 T0)
==647802==The signal is caused by a READ memory access.
==647802==Hint: this fault was caused by a dereference of a high value address (see register values below).  Disassemble the provided pc to learn which register was used.
    #0 0x55a827600582  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0x11582) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #1 0x55a8276863cb  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0x973cb) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #2 0x55a8276b10ff  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xc20ff) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #3 0x55a8276c281c  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd381c) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #4 0x55a8276c1409  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd2409) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #5 0x55a8276c12f6  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd22f6) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #6 0x55a8276c1189  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd2189) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #7 0x55a8276c1419  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd2419) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #8 0x55a8276c3738  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd4738) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #9 0x55a8276c1d19  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd2d19) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #10 0x55a8276c1827  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd2827) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #11 0x55a8276c2f31  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd3f31) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #12 0x55a8276c111a  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd211a) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #13 0x55a8276c3f7d  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd4f7d) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #14 0x55a8276c33a4  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd43a4) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #15 0x55a8276ed3b0  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xfe3b0) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #16 0x55a8276c324f  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd424f) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #17 0x55a8276c30cd  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0xd40cd) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)
    #18 0x7ff7d4160d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
    #19 0x7ff7d4160e3f  (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 490fef8403240c91833978d494d39e537409b92e)
    #20 0x55a8275ff6f4  (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0x106f4) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/user/id-map_from_iter_bug/target/debug/id-map_from_iter_bug+0x11582) (BuildId: dff809c9a31a3137db2de49565e329d1e844f67c) 
==647802==ABORTING

How to Build and Run the PoC:

RUSTFLAGS="-Zsanitizer=address" cargo +nightly-2024-02-01-x86_64-unknown-linux-gnu run

Details:

  • Compiler Version: rustc 1.77.0-nightly (11f32b73e 2024-01-31)
  • Library Version: id-map-0.2.1
  • OS: Ubuntu 22.04.5 LTS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions