andrewhickman / id-map Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Would it be possible to have a type parameter for IdMap that determines the Id type? I would like to use u16 instead of usize.
Hi there, we (Rust group @sslab-gatech) are scanning crates on crates.io for potential soundness bugs. We noticed a few panic safety issues in this library.
Lines 370 to 380 in a2fa8d4
The current values in the map are dropped and the ids
are updated up front. This means that if other.values.get_unchecked(id).clone()
panics, it can cause the previously dropped values to drop again.
Lines 169 to 180 in a2fa8d4
Since this reserves space for the value before calling ptr::write(space, f());
, if f
panics here, it can drop an already freed value.
Lines 192 to 203 in a2fa8d4
This code goes over to the ids to remove and calls drop_in_place
on them. However if the drop function for the type panics, the element gets dropped again when the IdMap
is dropped.
Code to recrate these problems is here:
#![forbid(unsafe_code)]
use id_map::IdMap;
use id_set::IdSet;
struct DropDetector(u32);
impl Drop for DropDetector {
fn drop(&mut self) {
println!("Dropping {}", self.0);
}
}
impl Clone for DropDetector {
fn clone(&self) -> Self { panic!("Panic on clone!"); }
}
fn main() {
//clone_from_panic_will_drop_invalid_memory();
//get_or_insert_with_leaves_state_inconsistent();
remove_set_leaves_state_inconsistent_if_drop_panics();
}
fn clone_from_panic_will_drop_invalid_memory() {
let mut map = IdMap::new();
map.insert(DropDetector(1));
let mut map_2 = IdMap::new();
map_2.insert(DropDetector(2));
map_2.clone_from(&map);
}
fn get_or_insert_with_leaves_state_inconsistent() {
let mut map : IdMap<DropDetector> = IdMap::with_capacity(0);
map.get_or_insert_with(0, || panic!("Panic in insertion function!"));
}
struct PanicsOnDrop(u32, bool);
impl Drop for PanicsOnDrop {
fn drop(&mut self) {
println!("Dropping {}", self.0);
if (self.1) {
self.1 = false;
panic!("Panicking on drop");
}
}
}
fn remove_set_leaves_state_inconsistent_if_drop_panics() {
let mut map = IdMap::new();
map.insert(PanicsOnDrop(1, true));
map.remove_set(&IdSet::new_filled(1));
}
Example code showing the difference in behavior:
extern crate id_map;
use id_map::IdMap;
fn main() {
// test 1
let mut map1 = IdMap::new();
for _ in 0..10 {
map1.insert("foo");
}
// remove all odd ids
for i in 0..5 {
map1.remove(i*2+1);
}
// prints {0, 2, 4, 6, 8}
println!("{:?}", map1.as_set());
// prints 1
println!("{}", map1.next_id());
// test2
let mut map2 = IdMap::new();
for _ in 0..10 {
map2.insert("foo");
}
// remove all odd ids
map2.retain(|id, _| id%2 == 0);
// prints {0, 2, 4, 6, 8}
println!("{:?}", map2.as_set());
// prints 10
println!("{}", map2.next_id());
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.